RemoteViews的应用
RemoteViews表示的是一个View结构,它可以在其他进程中显示。
RemoteViews在通知栏的应用
通过RemoteViews加载布局文件可以实现自定义通知效果。更新RemoteViews时,无法直接访问里面的View,必须通过RemoteViews所提供的一系列方法来更新View。
//设置TextView的文本
remoteViews.setTextViewText(R.id.text, "this is content.");
//设置ImageView的图片
remoteViews.setImageViewResource(R.id.icon, R.drawable.icon);
//设置点击事件
remoteViews.setOnClickPendingIntent(int viewId, PendingIntent pendingIntent);
emoteViews在桌面小部件上的应用
AppWidgetProvider是Android中提供的用于实现桌面小部件的类,继承BroadcastReceiver,其本质是一个BroadcastReceiver。
桌面小部件的开发分为如下几个步骤:
- 定义小部件界面
在res/layout目录下新建一个布局文件
- 定义小部件的配置信息
在res/xml目录下新建一个xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget"
android:minWidth="60dp"
android:minHeight="60dp"
android:updatePeriodMillis="3600000"
/>
定义小部件的实现类
在AndroidMainifest.xml中声明小部件
PendingIntent概述
PendingIntent表示在将来的某个时刻发生,Intent是立即发生。
PendingIntent的匹配规则:如果两个PendingIntent它们内部的Intent相同并且requestCode也相同,那么这两个PendingIntent就是相同的(如果两个Intent的ComponentName和intent-filter都相同,那么这两个Intent就是相同的,Extras不参与Intent匹配)。
flags的类型:
- FLAG_NO_CREAT
PendingIntent不会主动创建,如果当前PendingIntent之前不存在,那么getActivity、getService、getBroadcast方法返回null。这个标记位实际开发中很少见,它无法单独使用。 - FLAG_ONE_SHOT
PendingIntent只能使用一次,然后它会自动cancel,如果后续还有相同的PendingIntent,那么它们的send方法会调用失败。 - FLAG_CANCEL_CURRENT
PendingIntent如果已经存在,那么它们会被cancel,然后创建一个新的PendingIntent。 - FLAG_UPDATE_CURRENT
PendingIntent如果已经存在,那么它们会被更新,即它们的Intent中的Extras会被替换成最新的。
下面结合通知栏消息来阐述这几个标志位的用途。
NotificationManager.notify(int id, Notification notification)
如果notify方法的参数id相同,那么多次调用notify方法只能弹出一条通知,后续的通知会替换前面的通知;如果参数id不同,那么多次调用notify方法会弹出多条通知,这种情况下,如果PendingIntent匹配,分以下几种情况:
- FLAG_ONE_SHOT
后续通知中的PendingIntent会和第一条通知保持完全一致(包括Extras),单击任何一条通知后。剩余的通知均无法打开 - FLAG_CANCEL_CURRENT
只有最新的通知才可以打开,之前弹出的通知均无法打开 - FLAG_UPDATE_CURRENT
之前弹出的通知中的PendingIntent被更新(包括Extras),这些通知都是可以打开的
RemoteViews的内部机制
1、RemoteViews会通过Binder传递到SystemServer进程,系统通过LayoutInflater加载RemoteViews布局。
2、SystemServer更新View。set方法对View的更新不会立即执行,RemoteViews内部记录所有的更新View的操作,RemoteViews加载后才会执行这些更新操作。
Android系统并没有通过Binder去直接支持View的跨进程访问,而是通过将View的操作封装到Action对象中,并把Action对象被传递到远程进程来执行具体的操作。这样做的好处就是:
1、不需要定义大量Binder接口
2、通过在远程进程批量执行RemoteViews的更新操作,避免了大量的IPC操作,提高了应用的性能。