RemoteViews的作用和原理

RemoteViews

RemoteView是一种远程View,可以在其他进程中显示。RemoteView在安卓中的使用主要有两种:通知栏和桌面小部件。通知栏主要由NotifycationManager实现,桌面小部件主要由AppWidgetProvider实现,AppWidgetProvide其实是一个广播。二者都运行在其他进程中,即SystemServer进程中。

通知栏

在开发中可以使用自定义布局的通知栏时需要使用RemoteView:

 NotificationCompat.Builder builder1 = new NotificationCompat.Builder(this, Notification.CATEGORY_PROMO)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setTicker("helloWord")
                        .setWhen(System.currentTimeMillis());
                Intent mIntent = new Intent(this, NotifyDetailActivity.class);
                PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                Notification notification = builder1.build();
                RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_define_notify);
                remoteViews.setTextViewText(R.id.tv_title, "nihao");
                remoteViews.setTextViewText(R.id.tv_content, "nihao");
                remoteViews.setOnClickPendingIntent(R.id.open, pendingIntent);
                notification.contentView = remoteViews;
                notification.contentIntent = pendingIntent;
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.notify(1, notification);

RemoteView的创建主要由包名和布局文件决定。

桌面小部件

新建一个类继承AppWidgetProvider,需要在清单文件中注册,因为AppWidget是一个广播

public class MyAppWidgetProvide extends AppWidgetProvider {

在onReciver中创建一个小部件

  @Override
    public void onReceive(final Context context, Intent intent) {
        super.onReceive(context, intent);
        if (intent.getAction() == CLICK_ACTION) {
            Toast.makeText(context, "click", Toast.LENGTH_SHORT).show();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Bitmap srcbBit = BitmapFactory.decodeResource(context.getResources(), R.mipmap.bg_clear);
                    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                    for (int i = 0; i < 37; i++) {
                        float degree = (i * 10) % 360;
                        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
                        remoteViews.setImageViewBitmap(R.id.imageView, rotateBitmap(context, srcbBit, degree));
                        Intent mIntent = new Intent();
                        mIntent.setAction(CLICK_ACTION);
                        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, mIntent, 0);
                        remoteViews.setOnClickPendingIntent(R.id.imageView, pendingIntent);
                        appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidgetProvide.class), remoteViews);
                        SystemClock.sleep(300);
                    }
                }
            }).start();
        }
    }

RemoteView的内部机制

RemoteView没有提供findViewByid的方法获取View,但是提供了一系列的set方法例如setTextViewText等方法更新Ui,大部分的set方法是根据反射获取的。
通知栏和桌面小部件是通过NotifycationManager和AppWidgetManager管理的,这二者又通过Binder和SystemServer中NotifycationManagerService和AppWidgetManagerService通信,这就构成了进程间的通信,但是系统并没有通过Binder去支持所有的View和View的更新,而是将所有的View的操作放在了一个Action类中,当每次调用setXX方法时RemoteViews就会添加一个对应Action,当View进行更新操作时,就会将Action对象发送到远程,远程进程则会调用RemotesView的apply方法进行View的更新,最终View的更新操作则是由Action内部的apply方法控制的。
RemoteViews的作用和原理_第1张图片

本文参考《安卓开发艺术探索》。

你可能感兴趣的:(RemoteViews的作用和原理)