欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android通过RemoteViews实现跨进程更新UI示例

程序员文章站 2023-12-21 08:05:04
一、概述 前面一篇文章android通过aidl实现跨进程更新ui我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新ui是可行的,但有以下弊端: vi...

一、概述

前面一篇文章android通过aidl实现跨进程更新ui我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新ui是可行的,但有以下弊端:

  • view中的方法数比较多,在ipc中需要增加对应的方法比较繁琐。
  • view的每一个方法都会涉及到ipc操作,多次ipc带来的开销问题不容小觑。
  • view中方法的某些参数可能不支持ipc传输。例如:onclicklistener,它仅仅是个接口没有序列化。

接下来我们通过remoteviews实现跨进程更新ui

二、实现效果图

在同一个应用中有两个activity,mainactivity和temp2activity,这两个activity不在同一个进程中。

Android通过RemoteViews实现跨进程更新UI示例

现在需要通过temp2activity来改变mainactivity中的视图,即在mainactivity中添加两个button,也就是实现跨进程更新ui这么一个功能。

在mainactivity里点击“跳转到新进程activity”按钮,会启动一个新进程的temp2activity,我们先点击“绑定服务”,这样我们就启动了服务,再点击“aidl更新”按钮,通过调用handler来实现跨进程更新ui,点击返回,我们发现mainactivity页面中新添加了两个按钮,并且按钮还具有点击事件。

Android通过RemoteViews实现跨进程更新UI示例

三、核心代码

iremoteviewsmanager.aidl

里面提供了两个方法,一个是根据id更新textview里面的内容,一个是根据id添加view视图

// iremoteviewsmanager.aidl.aidl
package com.czhappy.remoteviewdemo;

interface iremoteviewsmanager {
  void addremoteview(in remoteviews remoteviews);
}

remoteviewsaidlservice.java

package com.czhappy.remoteviewdemo.service;

import android.app.service;
import android.content.intent;
import android.os.binder;
import android.os.bundle;
import android.os.ibinder;
import android.os.message;
import android.os.remoteexception;
import android.widget.remoteviews;

import com.czhappy.remoteviewdemo.iremoteviewsmanager;
import com.czhappy.remoteviewdemo.activity.mainactivity;

/**
 * description:
 * user: chenzheng
 * date: 2017/2/10 0010
 * time: 10:56
 */
public class remoteviewsaidlservice extends service {
  private static final string tag = "remoteviewsaidlservice";

  private binder remoteviewsbinder = new iremoteviewsmanager.stub(){
    @override
    public void addremoteview(remoteviews remoteviews) throws remoteexception {
      message message = new message();
      message.what = 1;
      bundle bundle = new bundle();
      bundle.putparcelable("remoteviews",remoteviews);
      message.setdata(bundle);
      new mainactivity.myhandler(remoteviewsaidlservice.this,getmainlooper()).sendmessage(message);
    }
  };

  public remoteviewsaidlservice() {

  }

  @override
  public ibinder onbind(intent intent) {
    return remoteviewsbinder;
  }

}

mainactivity.java

package com.czhappy.remoteviewdemo.activity;

import android.content.context;
import android.content.intent;
import android.os.bundle;
import android.os.handler;
import android.os.looper;
import android.os.message;
import android.support.v7.app.appcompatactivity;
import android.util.log;
import android.view.layoutinflater;
import android.view.view;
import android.widget.linearlayout;
import android.widget.remoteviews;
import android.widget.textview;

import com.czhappy.remoteviewdemo.r;

import java.lang.ref.weakreference;

public class mainactivity extends appcompatactivity {

  private static string tag = "mainactivity";
  private static linearlayout mlinearlayout;

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);

    mlinearlayout = (linearlayout) this.findviewbyid(r.id.mylayout);
  }

  public static class myhandler extends handler {
    weakreference<context> weakreference;
    public myhandler(context context, looper looper) {
      super(looper);
      weakreference = new weakreference<>(context);
    }
    @override
    public void handlemessage(message msg) {
      super.handlemessage(msg);
      log.i(tag, "handlemessage");
      switch (msg.what) {
        case 1: //remoteviews的aidl实现
          remoteviews remoteviews = msg.getdata().getparcelable("remoteviews");
          if (remoteviews != null) {
            log.i(tag, "updateui");

            view view = remoteviews.apply(weakreference.get(), mlinearlayout);
            mlinearlayout.addview(view);
          }
          break;
        default:
          break;
      }
    }

  };

  public void readygo(view view){
    intent intent = new intent(mainactivity.this, temp2activity.class);
    startactivity(intent);
  }

}

temp2activity.java

package com.czhappy.remoteviewdemo.activity;

import android.app.pendingintent;
import android.content.componentname;
import android.content.context;
import android.content.intent;
import android.content.serviceconnection;
import android.os.bundle;
import android.os.ibinder;
import android.os.remoteexception;
import android.support.annotation.nullable;
import android.support.v7.app.appcompatactivity;
import android.util.log;
import android.view.view;
import android.widget.remoteviews;

import com.czhappy.remoteviewdemo.iremoteviewsmanager;
import com.czhappy.remoteviewdemo.r;
import com.czhappy.remoteviewdemo.service.remoteviewsaidlservice;

/**
 * description:
 * user: chenzheng
 * date: 2017/2/9 0009
 * time: 16:05
 */
public class temp2activity extends appcompatactivity {

  private string tag = "temp2activity";

  private iremoteviewsmanager remoteviewsmanager;
  private boolean isbind = false;


  private serviceconnection remoteviewserviceconnection = new serviceconnection() {
    @override
    public void onserviceconnected(componentname name, ibinder service) {
      log.i(tag,"onserviceconnected");
      remoteviewsmanager = iremoteviewsmanager.stub.asinterface(service);

    }

    @override
    public void onservicedisconnected(componentname name) {
      //回收
      remoteviewsmanager = null;
    }
  };

  @override
  protected void oncreate(@nullable bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    this.setcontentview(r.layout.activity_temp);
  }

  /**
   * 绑定服务
   */
  public void bindservice(view view) {
    intent viewserviceintent = new intent(this,remoteviewsaidlservice.class);
    isbind = bindservice(viewserviceintent,remoteviewserviceconnection, context.bind_auto_create);
  }

  /**
   * 更新ui
   */
  public void updateui(view view){
    remoteviews remoteviews = new remoteviews(temp2activity.this.getpackagename(),r.layout.button_layout);

    intent intentclick = new intent(temp2activity.this,firstactivity.class);
    pendingintent openfirstactivity = pendingintent.getactivity(temp2activity.this,0,intentclick,0);
    remoteviews.setonclickpendingintent(r.id.firstbutton,openfirstactivity);

    intent secondclick = new intent(temp2activity.this,secondactivity.class);
    pendingintent opensecondactivity = pendingintent.getactivity(temp2activity.this,0,secondclick,0);
    remoteviews.setonclickpendingintent(r.id.secondbutton,opensecondactivity);

    remoteviews.setcharsequence(r.id.secondbutton,"settext","想改就改");
    try {
      remoteviewsmanager.addremoteview(remoteviews);
    } catch (remoteexception e) {
      e.printstacktrace();
    }
  }

  @override
  protected void ondestroy() {
    super.ondestroy();
    if(isbind){
      unbindservice(remoteviewserviceconnection);
      isbind = false;
    }

  }

}

androidmanifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.czhappy.remoteviewdemo">

  <application
    android:allowbackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsrtl="true"
    android:theme="@style/apptheme">
    <activity android:name=".activity.mainactivity">
      <intent-filter>
        <action android:name="android.intent.action.main" />

        <category android:name="android.intent.category.launcher" />
      </intent-filter>
    </activity>
    <activity android:name=".activity.firstactivity" />
    <activity android:name=".activity.secondactivity" />
    <activity
      android:name=".activity.temp2activity"
      android:process=":remote2" />

    <service android:name="com.czhappy.remoteviewdemo.service.remoteviewsaidlservice" />


  </application>

</manifest>

四、总结

remoteviews就是为跨进程更新ui而生的,内部封装了很多方法用来实现跨进程更新ui。但这并不代表remoteviews是就是万能的了,它也有不足之处,目前支持的布局和view有限

layout:

framelayout linearlayout relativelayout gridlayout

view:

analogclock button chronometer imagebutton imageview progressbar textview viewflipper listview gridview stackview adapterviewflipper viewstub

不支持自定义view 所以具体使用remoteviews还是aidl或者broadcastreceiver还得看实际的需求。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: