RemoteViews

2018-09-29  本文已影响0人  要学的东西太多了

1.RemoteViews是一种远程View,可以在其他进程中显示,而且提供了一系列操作来跨进程更新界面。常应用在通知栏和桌面小部件。
(1)在通知栏的应用如下:

        Intent intent = new Intent(this, ScrollTestActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,1
                ,intent,PendingIntent.FLAG_CANCEL_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"remoteView");
        RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.item_remoteview);
        remoteViews.setTextViewText(R.id.content,"你点我就能打开时钟");
        remoteViews.setTextViewText(R.id.time, TimeUtil.getStringDate());
        remoteViews.setImageViewResource(R.id.icon,R.mipmap.ic_launcher);
        remoteViews.setOnClickPendingIntent(R.id.content,pendingIntent);
        Notification notification = builder.setSmallIcon(R.mipmap.ic_launcher)
                .setTicker("跨进程的通知")
                .setContent(remoteViews)
                .setContentIntent(pendingIntent)
                .build();
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationManager.notify(2,notification);

(2)桌面小部件。注意,有些Android机的桌面小部件在运行程序后,还需要从小组件里面拖出来。桌面小部件一定要重写onUpdate方法,否则桌面小部件是无法显示的,不重写就要通过发广播在onReceive方法里去更新,如下:

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        DBLog.i(TAG,"更新");
        int count = appWidgetIds.length;
        for(int i=0;i<count;i++){
            updateWidget(context,appWidgetManager,appWidgetIds[i]);
        }
    }

    private void updateWidget(Context context, AppWidgetManager appWidgetManager,int appWidgetID){
        Intent clickIntent = new Intent();
        clickIntent.setAction(ACTION_START);
        PendingIntent clickPendingIntent = PendingIntent.getBroadcast(context,0,clickIntent,0);
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_notebook_small);
        remoteViews.setOnClickPendingIntent(R.id.openNote,clickPendingIntent);
        appWidgetManager.updateAppWidget(appWidgetID,remoteViews);
    }

其次,桌面小部件实质上是个广播,因此要在Androidmanifest里面注册:

<receiver android:name=".broadcastreceiver.TestAppWidgetProvider">
        <!--一定要有,resource为小部件的配置xml文件-->
        <meta-data
              android:name="android.appwidget.provider"
              android:resource="@xml/appwidget_provider" />
       <!--action必须加上android.appwidget.action.APPWIDGET_UPDATE,否则默认是不更新组件的-->
       <intent-filter>
              <action android:name="com.jmc.yyjr.broadcastreceiver.action.start" />
             <action android:name="com.jmc.yyjr.broadcastreceiver.action.over" />
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
       </intent-filter>
 </receiver>

2.PendingIntent表示一种即将发生的意图,Intent是马上发生的。PendingIntent支持三种意图:
(1)PendingIntent.getBroadcast(Context context, int requestCode,
Intent intent, @Flags int flags),意图发生时相当于context.sendBroadcast(intent)。
(2)PendingIntent.getActivity(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags),意图发生时相当于context.startActivity(intent)。
(3)PendingIntent.getService(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags),意图发生时相当于```context.startService(intent)。

3.PendingIntent的flags常见类型有:
FLAG_CANCEL_CURRENT(如果已经存在,那么前面的全部失效,系统会创建一个最新的PendingIntent);
FLAG_UPDATE_CURRENT(如果已经存在,则全部更新,即intent的Extras都会更新);
FLAG_ONE_SHOT(只能使用一次,使用后就取消,即便后面有相同PendingIntent也不能再使用)。

4.PendingIntent匹配规则为:如果两个PendingIntent的requestCode和intent都相同,那么这两个PendingIntent就是相同的。intent相同指的是intent-filter和ComponentName都相同。

5.RemoteViews支持的View类型有限,可用的有:
支持的布局有:FrameLayout、LinearLayout、RelativeLayout、GridLayout
支持的View有:AnalogClock、Button、ImageButton、ImageView、TextView、ProgressBar、Chronometer、ViewFlipper、ListView、GridView、StackView、ViewStub、AdapterViewFlipper
使用这些之外的都会抛异常,子类也不行。

6.RemoteViews的set系列方法实质上是添加Action,调用Notification的notify方法或APPWidgetManager的updateAPPWidget方法更新时才会去调用RemoteViews的apply方法,进而调用Action的apply方法。第一次的时候调用apply方法,它会加载并更新布局;后面更新都用reApply方法,只更新布局。

7.RemoteViews跨进程更新UI时,在com.android.support:appcompat-v7:23.0.1以上版本使用remoteViews.setInt(R.id.icon,"setImageResource",R.mipmap.app_icon)会报错。

8.同一应用的跨进程更新用这种方式:

RemoteViews remoteViews = intent.getExtras().getParcelable("view");
if(remoteViews !=null){
    View child = remoteViews.apply(Activity1.this,viewGroup);
    viewGroup.addView(child );
}

不同应用的跨进程更新,资源文件ID不可能相同,所以用下面这种方式:

RemoteViews remoteViews = intent.getExtras().getParcelable("view");
            if(remoteViews!=null){
                int layoutId = getResources().getIdentifier("item_remoteview","layout",getPackageName());
                View view = getLayoutInflater().inflate(layoutId,layout,false);
                remoteViews.reapply(Activity1.this,view);
                layout.addView(view);
            }
上一篇 下一篇

猜你喜欢

热点阅读