Android开发艺术探索(4) --- RemoteViews
2020-01-05 本文已影响0人
官子寒
提供了一组基础的操作用于跨进程更新界面的View,常应用在通知栏和桌面小部件
1. RemoteViews的应用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.send_notification);
btn.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onClick(View view) {
send_notification();
}
});
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void send_notification(){
NotificationChannel channel = new NotificationChannel("1","my_channel", NotificationManager.IMPORTANCE_DEFAULT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentText("Notification").setWhen(System.currentTimeMillis());
Intent intent = new Intent(this, secondActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_notification);
remoteViews.setTextViewText(R.id.msg,"chapter_5");
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , new Intent(this, secondActivity.class),PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.click, pendingIntent);
builder.setCustomContentView(remoteViews);
builder.setContentIntent(pi);
builder.setSmallIcon(R.drawable.ic_launcher_background);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
builder.setChannelId("1");
Notification notification = builder.build();
manager.notify(1,notification);
}
}
- 注意:适配问题,Android Q以上需要设置
channel
2. PendingIntent概述
一种处于
pending状态的意图,也就是说接下来有一个Intent将在某一个待定的时刻发生
- 因为
RemoteViews运行在远程进程中,因此不能用setOnClickListener方法来设置单击事件,要想设置则必须使用PendingIntent -
PendingIntent支持三种待定意图:启动Activity、启动Service和发送广播
| 方法名 | 作用 |
|---|---|
getActivity(Context context, int requestCode, Intent intent, int flags) |
获得一个PendingIntent,当该意图发生时,相当于Context.startActivity(Intent)
|
getService(Context context, int requestCode, Intent intent, int flags) |
获得一个PendingIntent,当该意图发生时,相当于Context.startService(Intent)
|
getBroadcast(Context context, int requestCode, Intent intent, int flags) |
获得一个PendingIntent,当该意图发生时,相当于Context.sendBroadcast(Intent)
|
-
PendingIntent的匹配规则:Intent相同,且requestCode相同 -
Intent匹配规则:ComponentName和intent-filter相同 -
flags常见的类型:FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT
FLAG_ONE_SHOT:当前描述的PendingIntent只能被使用一次,然后就会自动cancel
FLAG_NO_CREATE:当前描述的PendingIntent不能被主动创建
FLAG_CANCEL_CURRENT:当前描述的PendingIntent如果已经存在,那么它们都会被cancel,然后系统会创建一个新的PendingIntent
FLAG_UPDATE_CURRENT:当前描述的PendingIntent如果已经存在,那么它就会被更新
判断逻辑
3. RemoteViews的内部机制
构造函数:RemoteViews(String packageName, int layoutId)
- 支持的
layout:FrameLayout,LinearLayout,RelativeLayout,GridLayout - 支持的
View:AnalogClock,Button,Chronometer,ImageButton,ImageView,ProgressBar,TextView,ViewFlipper,ListView,GridView,StackView,AdapterViewFlipper,ViewStub
RemoteViews访问View元素只能通过一系列set元素来完成
| 方法名 | 作用 |
|---|---|
setTextView() |
设置TextView的文本 |
setTextViewTextSize() |
设置TextView的字体大小 |
setTextColor() |
设置TextView的字体颜色 |
setImageResource() |
设置ImageView的图片资源 |
setOnClickListener() |
设置ImageView的图片资源 |
RemoteViews内部机制
- 首先通过一系列
set方法将View操作保存为一系列的Action存储起来 - 然后在远端进程中通过
remoteViews的apply方法来更新UI界面,实现远程刷新界面的效果
作用:
- 不需要定义大量Binder接口
- 避免了大量的IPC操作,提高了程序的型嫩
4. RemoteViews Demo
BroadCast.java
public class BroadCast extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broad_cast);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.simulated_notification);
remoteViews.setTextViewText(R.id.textForTest, "msg from Process");
PendingIntent pi = PendingIntent.getActivity(this,0, new Intent(this, MainActivity.class),PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.textForTest, pi);
Intent intent = new Intent("com.example.remoteviews");
intent.putExtra("com.example.remoteviews", remoteViews); //在发送intent的时候将remoteViews发送出去
sendBroadcast(intent);
Log.d("guanzihan","已发送");
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private LinearLayout mRemoteViewsContent;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
RemoteViews remoteViews = intent.getParcelableExtra("com.example.remoteviews");
if(remoteViews != null){
updateUI(remoteViews);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
public void initView(){
mRemoteViewsContent = (LinearLayout)findViewById(R.id.remoteViews_content);
IntentFilter intentFilter = new IntentFilter("com.example.remoteviews");
registerReceiver(broadcastReceiver,intentFilter);
startActivity(new Intent(this, BroadCast.class));
}
public void updateUI(RemoteViews remoteViews){
View view = remoteViews.apply(this, mRemoteViewsContent);
mRemoteViewsContent.addView(view);
}
}
MainActivity