Android通过RemoteViews实现跨进程更新UI示例
一、概述
前面一篇文章android通过aidl实现跨进程更新ui我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新ui是可行的,但有以下弊端:
- view中的方法数比较多,在ipc中需要增加对应的方法比较繁琐。
- view的每一个方法都会涉及到ipc操作,多次ipc带来的开销问题不容小觑。
- view中方法的某些参数可能不支持ipc传输。例如:onclicklistener,它仅仅是个接口没有序列化。
接下来我们通过remoteviews实现跨进程更新ui
二、实现效果图
在同一个应用中有两个activity,mainactivity和temp2activity,这两个activity不在同一个进程中。
现在需要通过temp2activity来改变mainactivity中的视图,即在mainactivity中添加两个button,也就是实现跨进程更新ui这么一个功能。
在mainactivity里点击“跳转到新进程activity”按钮,会启动一个新进程的temp2activity,我们先点击“绑定服务”,这样我们就启动了服务,再点击“aidl更新”按钮,通过调用handler来实现跨进程更新ui,点击返回,我们发现mainactivity页面中新添加了两个按钮,并且按钮还具有点击事件。
三、核心代码
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还得看实际的需求。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。