完全理解Android中的RemoteViews

一、什么是RemoteViews

RemoteViews翻译过来就是远程视图.顾名思义,RemoteViews不是当前进程的View,是属于SystemServer进程.应用程序与RemoteViews之间依赖Binder实现了进程间通信.

二、RemoteViews的用法

RemoteViews使用最多的场合是通知栏和桌面小插件. 以通知栏为例,讲解下它的用法.

1、新建一个Notification

这里要注意是在android3.0之前都是使用如下的形式构建一个Notification

        // 1.新建一个Notification对象         Notification mNotification = new Notification();         // 2.添加属性,比如标题、内容、优先级、图片等         mNotification.tickerText = "这是通知栏的标题";         mNotification.icon = R.drawable.ic_launcher;         mNotification.flags=Notification.FLAG_NO_CLEAR;         mNotification.setLatestEventInfo(this, "这是内容", "这是标题", null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在3.0之后官方推荐使用建造者模式创建Notification.

Notification mNotification = new Notification.Builder(this)         .setContentTitle("这是标题 ")             .setContentText("这是内容")                 .setSmallIcon(R.drawable.ic_launcher)                         .build();
  • 1
  • 2
  • 3
  • 4
  • 5

Notification有很多属性,这里列举一些

 - setContentTitle       设置标题  - setContentText        设置内容  - setLargeIcon          设置通知栏大图标  - setSmallIcon          设置通知栏小图标  - setContent            设置RemoteViews  - setContentIntent      当通知条目被点击,就执行这个被设置的Intent.  - setDeleteIntent       当用户点击"Clear All Notifications"按钮区删除所有的通知的时候,这个被设置的Intent被执行  - setLights             设置闪光灯  - setSound              设置声音  - setPriority           设置优先级 

2、设置Notification的RemoteViews

如果要给通知栏使用自定义布局就要使用RemoteViews了,传入包名和相应的布局.

RemoteViews mRemoteViews=new RemoteViews("com.example.remoteviewdemo", R.layout.remoteview_layout);
  • 1

然后通过setContent()传入RemoteViews 对象即可.

这里顺便讲一下PendingIntent,PendingIntent是”延迟意图”的意思,就是当满足某一条件时出触发这个Intent.通过PendingIntent的getActivity、getBroadcast、getService等分别构建一个打开对应组件的延迟Intent. 
传入四个参数,context、intent、requestCode(自定义)、flag.

Intent intent=new Intent(MainActivity.this,MainActivity.class); PendingIntent mPendingIntent=PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • 1
  • 2

PendingIntent有4种flag.

 - FLAG_ONE_SHOT                只执行一次  - FLAG_NO_CREATE               若描述的Intent不存在则返回NULL值  - FLAG_CANCEL_CURRENT          如果描述的PendingIntent已经存在,则在产生新的Intent之前会先取消掉当前的  - FLAG_UPDATE_CURRENT          总是执行,这个flag用的最多 

3、获取通知管理者

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  • 1

4、弹出通知

调用notify方法,传入一个id(自定义)和通知实例即可.

manager.notify(1, mNotification);
  • 1

5、例子

我用一个按钮弹出通知,点击这个通知时进入到该Activity

public class MainActivity extends Activity {      private NotificationManager manager;     private Notification mNotification;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         //1.创建RemoteViews实例         RemoteViews mRemoteViews=new RemoteViews("com.example.remoteviewdemo", R.layout.remoteview_layout);          //2.构建一个打开Activity的PendingIntent         Intent intent=new Intent(MainActivity.this,MainActivity.class);         PendingIntent mPendingIntent=PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);          //3.创建一个Notification         mNotification = new Notification.Builder(this)         .setSmallIcon(R.drawable.ic_launcher)         .setContentIntent(mPendingIntent)         .setContent(mRemoteViews)         .build();          //4.获取NotificationManager         manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);          Button button1 = (Button) findViewById(R.id.button1);         button1.setOnClickListener(new OnClickListener() {              @Override             public void onClick(View v) {                 //弹出通知                 manager.notify(1, mNotification);             }         });      } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

如下图

这里写图片描述

6、改变RemoteViews的布局

RemoteViews并不能直接获得控件实例,然后对控件进行操作.它提供了 
setTextViewText(viewId, text)、setImageViewResource(viewId, srcId)等方法进行操作,传入控件id和相应的修改内容. 
列举一下常用的属性

 - setTextViewText(viewId, text)                     设置文本  - setTextColor(viewId, color)                       设置文本颜色  - setTextViewTextSize(viewId, units, size)          设置文本大小   - setImageViewBitmap(viewId, bitmap)                设置图片  - setImageViewResource(viewId, srcId)               根据图片资源设置图片  - setViewPadding(viewId, left, top, right, bottom)  设置Padding间距  - setOnClickPendingIntent(viewId, pendingIntent)    设置点击事件  

我这里就以setTextViewText改变文本的属性来讲解改变RemoteViews的原理. 
我在原来的代码上加上一个按钮点击改变内容

Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() {              @Override             public void onClick(View v) {                 mRemoteViews.setTextViewText(R.id.remote_content, "改变了内容");                 manager.notify(1, mNotification);             }         });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

看下效果

这里写图片描述

三、RemoteViews的改变原理

1.setTextViewText方法代码如下

public class RemoteViews implements Parcelable, Filter {     ...... public void setTextViewText(int viewId, CharSequence text) {         setCharSequence(viewId, "setText", text);     }     ......     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.调用了setCharSequence方法

public class RemoteViews implements Parcelable, Filter {     ...... public void setCharSequence(int viewId, String methodName, CharSequence value) {         addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR_SEQUENCE, value));     }      ......     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.在setCharSequence方法里调用了addAction方法,传入一个ReflectionAction实例,ReflectionAction继承自Action,它是用反射调用的

private final class ReflectionAction extends Action {     ......     ReflectionAction(int viewId, String methodName, int type, Object value) {             this.viewId = viewId;             this.methodName = methodName;             this.type = type;             this.value = value;         }    ......    }     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4.看下addAction方法,用了一个集合来保存Action实例,然后更新已使用内存的统计情况

public class RemoteViews implements Parcelable, Filter {     ...... private void addAction(Action a) {          if (mActions == null) {             mActions = new ArrayList<Action>();         }         //添加Action         mActions.add(a);          // 更新已使用内存的统计情况         a.updateMemoryUsageEstimate(mMemoryUsageCounter);     }     ......    }   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这一步之后,会调用

manager.notify(1, mNotification);
  • 1

来更新,追踪这个notify方法.

public class NotificationManager {     ...... public void notify(String tag, int id, Notification notification)     {          ......          INotificationManager service = getService();          try {             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,                     stripped, idOut, UserHandle.myUserId());          ......                 }     ......     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5.上面会调用getService方法返回INotificationManager这个系统服务,它是在SystemServer进程添加的.然后该服务调用 enqueueNotificationWithTag方法最后层层调用到

public class NotificationManagerService extends INotificationManager.Stub {     ...... StatusBarNotification n = new StatusBarNotification(pkg, id, tag, r.uid, r.initialPid, notification); try {                      mStatusBar.updateNotification(r.statusBarKey, n)      }     ......     } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

新建了StatusBarNotification实例,然后调用updateNotification方法. 
这个方法会进入到

public class PhoneStatusBar extends StatusBar {     ...... public void updateNotification(IBinder key, StatusBarNotification notification) {     ......      final RemoteViews contentView = notification.notification.contentView;     ......     contentView.reapply(mContext, oldEntry.content);     ......     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

会调用StatusBarNotification 的notification.contentView返回RemoteViews 对象,然后调用reapply方法.

6.回到RemoteViews 的reapply方法

public class RemoteViews implements Parcelable, Filter {     ...... public void reapply(Context context, View v, OnClickHandler handler) {   RemoteViews rvToApply = getRemoteViewsToApply(context);  ......  rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);      }  private void performApply(View v, ViewGroup parent, OnClickHandler handler) {         if (mActions != null) {             handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;             final int count = mActions.size();             for (int i = 0; i < count; i++) {                 Action a = mActions.get(i);                 //调用apply方法                 a.apply(v, parent, handler);             }         }     }       ......     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

最终调用apply方法,在这里加载新的布局,RemoteViews就是这么完成的.

public class RemoteViews implements Parcelable, Filter {     ...... public View apply(Context context, ViewGroup parent, OnClickHandler handler) { RemoteViews rvToApply = getRemoteViewsToApply(context);         View result; LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);         ......         //加载布局         result = inflater.inflate(rvToApply.getLayoutId(), parent, false);          rvToApply.performApply(result, parent, handler);          return result;     }      ......     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

总结

RemoteViews运行在SystemServer进程,更新RemoteViews要通过Binder获取到对应的服务然后调用RemoteViews内部的apply方法加载更新布局.

转载于:https://www.cnblogs.com/wxmdevelop/p/7099745.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/488040.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

各大媒体优劣对比_吉利星瑞特别版对比朗逸,亮点只有性价比?

据悉&#xff0c;吉利汽车推出了星瑞特别版车型——星瑞设计师推荐款&#xff0c;新车已于10月11日的11:00开启抢购&#xff0c;限量3000辆&#xff0c;抢购价格为13.77万元。其中值得注意的是&#xff0c;新车的抢购流程有所不同&#xff0c;想参与抢购的消费者需要先完成吉利…

【推广】实用命令——tldr

碎碎念如题&#xff0c;通常遇到一个新的命令需要查询其帮助的时候&#xff0c;一般使用command -h或者man command来查询&#xff0c;但是&#xff0c;有时候仅仅想知道这个命令怎么用&#xff0c;并不想知道具体含义啊(这个命令可能不常用&#xff0c;没有必要仔细阅读手册)&…

Nature重大突破!将皮肤细胞直接转化成感光细胞让小鼠重见光明!

图片来源&#xff1a;https://cn.bing.com本文系生物谷原创编译&#xff0c;欢迎分享&#xff0c;转载须授权&#xff01;研究人员发现了一种直接将皮肤细胞重新编程成用于视觉的光敏杆状感光器的技术。实验室制造的杆状体使失明的老鼠能够在细胞移植到眼睛后探测到光线。这项研…

时间组件选择一个时间段_衡南(光伏支架组件安装)施工队

衡南(光伏支架组件安装)施工队光伏支架安装本行业的技术人员应该了解&#xff0c;本发明不受上述实施例的限制&#xff0c;上述实施例和说明书中描述的只是说明本发明的原理&#xff0c;在不脱离本发明精神和范围的前提下&#xff0c;本发明还会有各种变化和改进&#xff0c;安…

DNA存储,拯救人类数据危机的良方?

来源&#xff1a;脑极体开一个脑洞&#xff1a;如果地球正在面临一场马上到来的毁灭性星际灾害&#xff0c;人类又想尽可能地保存地球的生命和文明&#xff0c;在现有条件下&#xff0c;该怎么办&#xff1f;像大刘一样让地球停止自转然后逃离太阳系&#xff0c;这恐怕来不及了…

oracle数据库dblink创建语句_「运维实验」——达梦数据库DBlink连接Oracle配置

经过昨天达梦数据库间DBlink配置&#xff08;具体操作可回看上一篇文章&#xff09;&#xff0c;今天做延伸实验。实验环境说明Oracle数据库1&#xff1a;192.168.80.40 ora11g RHEL 6.5 64位达梦数据库1&#xff1a;192.168.80.41 DMSERVER2 RHEL 6.5 64位oracle数据库版本&am…

智能经济的动力,从人工智能到超级智能

作者&#xff1a;刘锋前言&#xff1a;本文是根据研讨会发言形成的探讨性文章&#xff0c;主要阐述了智能经济的产生本质上是科技生态发生重大变化后的产物。提出智能经济运转的动力除了人工智能&#xff0c;人类的智能&#xff0c;互联网大脑模型的超级智能也是新出现的要素。…

损失函数_SRGAN损失函数(目标函数)详解

概要SRGAN的特点之一就是引进了损失感知函数&#xff0c;由此提升了超分辨率之后的细节信息。本文主要像您介绍SRGAN使用的损失函数&#xff0c;及其Keras实现。损失函数公式这是原文中给出的损失函数。容易看出&#xff0c;此损失函数包括两部分&#xff0c;第一部分是感知损失…

PHP获取本月起始和终止时间戳

一、本月起始和结束 //获取本月开始的时间戳 $beginThismonthmktime(0,0,0,date(m),1,date(Y)); //获取本月结束的时间戳 $endThismonthmktime(23,59,59,date(m),date(t),date(Y)); View Code二、上月起始和结束 写法一&#xff1a; $m date(Y-m-d, mktime(0,0,0,date(m)-1,1,…

人工智能细分领域龙头企业排行榜单

来源&#xff1a;互联网周刊2020年3月4日&#xff0c;中共中央政治局常务委员会召开会议&#xff0c;提出要发力于科技端的基础设施建设&#xff0c;人工智能成为“新基建”七大版块中的重要一项。“新基建”不同于传统思路&#xff0c;其本质是信息数字化的基础设施建设&#…

基于原版Hadoop的YDB部署(转)

YDB依赖环境准备 一、硬件环境 硬件如何搭配&#xff0c;能做到比较高的性价比&#xff0c;不存在短板。合理的硬件搭配&#xff0c;对系统的稳定性也很关键。 1.CPU不是核数越高越好&#xff0c;性价比才是关键。 经常遇到很多的企业级客户&#xff0c;他们机器配置非常高&…

物联网基石,五大领域对智能传感器的需求暴涨

来源&#xff1a;仪商网 传感器好比人的眼耳口鼻&#xff0c;但又不仅仅只是人的感官那么简单&#xff0c;它甚至能够采集到更多的有用信息。既然如此&#xff0c;就可说这些传感器是整个物联网系统工作的基础&#xff0c;正是因为有了传感器&#xff0c;物联网系统才有内容传递…

c6011取消对null指针的引用_C/C++学习笔记——C提高:指针强化

指针是一种数据类型指针变量指针是一种数据类型&#xff0c;占用内存空间&#xff0c;用来保存内存地址。void test01(){ int* p1 0x1234; int*** p2 0x1111; printf("p1 size:%d\n",sizeof(p1)); printf("p2 size:%d\n",sizeof(p2)); //指针是变…

现在的人工智能只是“窄AI”?

来源丨The Next Web编辑丨科技行者1956年&#xff0c;由数学系年轻的助理教授John McCarthy领导的科学家小组齐聚新罕布什尔州的达特茅斯学院&#xff0c;计划进行一个为期六周且雄心勃勃的项目&#xff1a;创建一种能够“使用语言、形式抽象与概念&#xff0c;帮助人类解决各类…

需要单机还是集群部署_单机、集群和分布式(微服务结构)的区别

一、单机单机就是所有的业务全部写在一个项目中&#xff0c;部署服务到一台服务器上&#xff0c;所有的请求业务都由这台服务器处理。显然&#xff0c;当业务增长到一定程度的时候&#xff0c;服务器的硬件会无法满足业务需求。自然而然地想到一个程序不行就部署多个喽&#xf…

查询 oracle_ORACLE数据库查询语句

Oracle数据库————SQL基本查询一、涉及内容1.掌握SELECT 语句的基本语法。2.掌握常用函数的使用。二、具体操作(一)使用Scott方案下的emp表和dept表&#xff0c;完成以下操作&#xff1a;1.查询部门编号是20的员工信息。2.查询工作为CLERK的员工号、员工名和部门号&#xff…

2020年中国新基建产业报告(收藏)

来源&#xff1a;董秘君未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0c;开展世界人工智能智商评测&#xff1b;开展互联网&#xff08;城市&#xff09;云脑研究计划&#xff0c;构建互联网&#xff08;城市&#xff09;云脑技术和企业图谱&a…

从云到端,谷歌的AI芯片2.0

来源&#xff1a;脑极体 得芯片者得天下。我们可以把这句话再延伸一下说&#xff0c;得AI芯片者得未来的天下。对于智能终端厂商来说&#xff0c;能够自研SoC芯片似乎才是顶级实力的象征。众所周知&#xff0c;盘踞全球智能手机前三甲的三星、华为、苹果&#xff0c;无一例外都…

Real-Time Volumetric Cloudscapes

实时体积云景 GPU Pro 7 实时体积云景的翻译 4.1 概览 游戏中的实时体积云通常为了提高渲染效率而降低质量。最成功的方法仅限于低空蓬松半透明的层状云。我们提出了一种体积解决方案&#xff0c;可以使用不断变化并且逼真的结果填充天空&#xff0c;来描绘高海拔卷云和所有…

语言条件语序心得_考研分享 | 王远新语言学教程要点总结(第五章)

点击上方蓝字&#xff0c;关注我吧作者|雨 轩编辑|武思文上次小编分享了王远新老师《语言学教程》的第四章&#xff1a;考研分享 | 王远新《语言学教程》要点总结(第四章)&#xff0c;今天小编为大家带来的是第五章的要点分享&#xff0c;希望可以帮到考研的你。第五章 语法关…