美文网首页viewAndroid开发经验谈Android开发
Android开发艺术探索(4) --- RemoteViews

Android开发艺术探索(4) --- RemoteViews

作者: 官子寒 | 来源:发表于2020-01-05 08:47 被阅读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匹配规则:ComponentNameintent-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)

  • 支持的layoutFrameLayout, LinearLayout, RelativeLayout, GridLayout
  • 支持的ViewAnalogClock, 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存储起来
  • 然后在远端进程中通过remoteViewsapply方法来更新UI界面,实现远程刷新界面的效果
作用
  1. 不需要定义大量Binder接口
  2. 避免了大量的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

相关文章

网友评论

    本文标题:Android开发艺术探索(4) --- RemoteViews

    本文链接:https://www.haomeiwen.com/subject/svbmoctx.html