1、本问将以Notifaction(通知栏) 和 AppWidgetProvider (桌面小部件)为切入点来讲解RemoteViews。
2、RemoteViews 继承了 Parcable,因此其对象具有跨进程的能力。
3、因为RemoteViews 可以跨进程,因此无论是通知栏还是桌面小部件,其他进程都可以生产RemoteViews然后通过广播或者Binder进行跨进程传送。
4、但是,RemoteVies只支持少量的几种布局控件,以下为其支持的布局控件(子类,父类,自定义均不包括):
Layout: FrameLayout、RelativeLayout、LinearLaout、GridLayout
View:AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、Adapter ViewFlipper、ViewStub。
5、RemoteVies 非常重要的是使用 PendingIntent ,PendingIntent 可以将其拆解来看 Pending 译为即将发生,Intent即是4大组件之一,因此PendingIntent就是说明了未来在某个时刻才会发生而不是立即发生,这就涉及到RemoteViews的机制,后续会进行讲解。
6、PendingIntent的实现方式如下图:
Intent intentClick = new Intent(CLICK_ACITON);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, PendingIntent.FLAG_UPDATE_CURRENT);
context,是android的上下文.
0,requestCode一般为0,自己根据情况定义。
intentClick,是一个Intent,从这里可以看出PendingIntent最终的效果实现还是通过 Intent来实现的。
PendingIntent.FLAG_UPDATE_CURRENT,是flag,以下对PendingIntent的flag进行讲解。
7、PendingIntent的4种flag。
PendingIntent.FLAG_ONE_SHOT:当前的PendingIntent只会被使用一次,然后他就会被自动取消,后续相同的PendingIntent不会再生效。
PendingIntent.FLAG_NO_CREATE:PendingIntent不会被创建,如果不存在则getActivity,getBroadcast等返回null。
PendingIntent.FLAG_CANCEL_CURRENT:如果PendingIntent已经存在,那么它会被取消,系统会重新创建一个新的PendingIntent。例如,通知栏消息,一旦被取消,后续无法再打开,只有最新的一条才能打开。
PendingIntent.FLAG_UPDATE_CURRENT,如果PendingIntent已经存在,那么就更新此PendingIntent,也就是之前弹出的 PendingIntent 会被更新,包括Extact.
8、 PendingIntent 三种获取方法的说明。Intent启动三个类型组件 activity,service,broadcast都有自己的一套方法,那么PendingIntent是通过getActivity,getBroadcast,getService这三个方法来获取的。
Intent intentClick = new Intent(CLICK_ACITON);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widget_image_one, pendingIntent);
例如以上代码,PendingIntent.getBroadcast 其获取PendingIntent是个广播类型的PendingIntent,其他2个方法同理。
remoteViews.setOnClickPendingIntent 设置了控件R.id.widget_image_one的点击事件,其关联 广播类型的pendingIntent,该控件点击会发送一个aciton为CLICK_ACITON的广播。
9、以下来看一个完整生成RemoteViews的代码:
private RemoteViews createCustomRemoteViews2(){
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.my_remoteviews_button_layout); //remoteViews布局为my_remoteviews_button_layout
if(isPlay){
remoteViews.setImageViewResource(R.id.play_button, R.drawable.btn_pause); //ImageView控件设置图片
}else{
remoteViews.setImageViewResource(R.id.play_button, R.drawable.btn_play);
}
remoteViews.setTextViewText(R.id.song_singer, "周杰伦"); //文本控件R.id.song_singer,设置文字
remoteViews.setTextViewText(R.id.tv_custom_song_name, "双节棍");
Intent intent1 = new Intent(CLICK_ACTION); //生成第一个action,本控件会触发一个广播
intent1.putExtra(INTENT_BUTTONID_TAG,PRE_CLICK_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.pre_button, pendingIntent);
Intent intent2 = new Intent(CLICK_ACTION); //生成第二个action,本控件会触发一个广播
intent2.putExtra(INTENT_BUTTONID_TAG, PLAY_CLICK_ACTION);
PendingIntent playIntent = PendingIntent.getBroadcast(this, 1, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.play_button, playIntent);
Intent intent3 = new Intent();
intent3.putExtra(INTENT_BUTTONID_TAG, NEXT_CLICK_ACTION); //生成第三个action,本控件会触发一个广播
PendingIntent nextIntent = PendingIntent.getBroadcast(this, 1, intent3, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.next_button, nextIntent);
return remoteViews;
}
以上代码可以看出,首先RemoteViews需要一个布局文件,跟其他view一样。并且可以给RemoteViews的布局文件进行设值。如果需要给布局文件的某个控件设置点击事件,那么必须需要一个 PendingIntent ,而PendingIntent则需要一个intent,intent和普通的没有什么区别,可以设置aciton,category,data,extract等。本控件是什么类型的,则由getBroadcast、getActiviy,getService来决定。例如以上3个控件点击均会发送一个广播。
10、remoteViews 设置一个view操作不会马上执行(如果频繁的跨进程操作,结果可想而知)。而是每个view操作都会在内部当成一个aciton保存起来,当进行NotificationManager.notify()或者AppWidgetManager.updateAppWidget 之后进行顺序处理。以下为其截图。
以下是一个notifaction完整的代码:
这里写代码片
package com.example.kingsoft.MyRemoteViews;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.widget.Button;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.example.kingsoft.CustomAdapter.R;
public class RemoteViews2Activity extends Activity implements View.OnC