前言

上一篇文章《Android 关于RemoteViews的理解(一)》介绍了RemoteViews的使用场景,我们学习东西的时候要知其然知其所以然。我之前考虑一篇文章就可以说明RemoteViews的内部机制了,但是当我仔细查阅资料学习之后发现要说透这个可能会需要几篇文章,所以关于RemoteViews的内部机制会拆分成几篇文章,这里是第一篇


1:构造方法及支持的View类型

在正式了解RemoteViews内部机制前我们有必要了解下RemoteViews支持的View类型,创建RomoteViews最常用的方法是:

 val remoteViews = RemoteViews(packageName, R.layout.xxx)

这个构造方法的源码如下:

/*** Create a new RemoteViews object that will display the views contained* in the specified layout file.** @param packageName Name of the package that contains the layout resource* @param layoutId The id of the layout resource*/public RemoteViews(String packageName, int layoutId) {this(getApplicationInfo(packageName, UserHandle.myUserId()), layoutId);}

其中packageName是当前应用的包名,layoutId是需要加载的布局文件。既然RemoteViews其中一个应用场景是在通知栏,这就限定了某些View它是不支持的,比如在通知栏里使用Edittext,这个应用场景是无法想象的,下面为谷歌官方开发文档中列出的RemoteViews支持的所有类型:

layouts

AdapterViewFlipper
FrameLayout
GridLayout
GridView
LinearLayout
ListView
RelativeLayout
StackView
ViewFlipper

widgets

AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextClock
TextView

值得注意的是RemoteViews只支持上述View类型而且不支持他们的子类,以及其他自定义View,我知道到这里肯定有人会去验证一波,所以我就直接帮你们验证了,当我在自定义的通知栏中使用了CheckBox,通知栏没有弹出,查看Logcat可以看到:

2020-12-22 21:54:24.752 1170-1283/? E/Netd: getNetworkForDns: getNetId from enterpriseCtrl is netid 0
2020-12-22 21:54:24.931 2199-2199/? E/StatusBar: couldn't inflate view for notification com.sjr.remoteviewsdemo/0x1android.view.InflateException: Binary XML file line #12 in com.sjr.remoteviewsdemo:layout/view_notification: Binary XML file line #12 in com.sjr.remoteviewsdemo:layout/view_notification: Error inflating class android.widget.CheckBoxCaused by: android.view.InflateException: Binary XML file line #12 in com.sjr.remoteviewsdemo:layout/view_notification: Error inflating class android.widget.CheckBoxCaused by: android.view.InflateException: Binary XML file line #12 in com.sjr.remoteviewsdemo:layout/view_notification: Class not allowed to be inflated android.widget.CheckBox

上面的异常信息表明CheckBox不能在RemoteViews中使用。当然其他的自定义View想要验证的可以自己走一下,异常跟上面的一致,只是控件名称换了而已。

2:RemoteViews内部机制

RemoteViews是在远程进程中显示,所以不能直接使用findViewById,也就无法访问直接访问View里面的元素,二十通过RemoteViews提供的一系列set方法来完成,官方文档提供的set方法如下:

void setFloat(int viewId, String methodName, float value)
Call a method taking one float on a view in the layout for this RemoteViews.void    setIcon(int viewId, String methodName, Icon value)
Call a method taking one Icon on a view in the layout for this RemoteViews.void setImageViewBitmap(int viewId, Bitmap bitmap)
Equivalent to calling ImageView#setImageBitmap(Bitmap)void  setImageViewIcon(int viewId, Icon icon)
Equivalent to calling ImageView#setImageIcon(Icon)void  setImageViewResource(int viewId, int srcId)
Equivalent to calling ImageView#setImageResource(int)void   setImageViewUri(int viewId, Uri uri)
Equivalent to calling ImageView#setImageURI(Uri)void    setInt(int viewId, String methodName, int value)
Call a method taking one int on a view in the layout for this RemoteViews.void  setLabelFor(int viewId, int labeledId)
Equivalent to calling View#setLabelFor(int).void    setLightBackgroundLayoutId(int layoutId)
Provides an alternate layout ID, which can be used to inflate this view.void    setLong(int viewId, String methodName, long value)
Call a method taking one long on a view in the layout for this RemoteViews.void setOnClickFillInIntent(int viewId, Intent fillInIntent)
When using collections (eg.void setOnClickPendingIntent(int viewId, PendingIntent pendingIntent)
Equivalent to calling View.setOnClickListener(android.view.View.OnClickListener) to launch the provided PendingIntent.void  setOnClickResponse(int viewId, RemoteViews.RemoteResponse response)
Equivalent of calling View.setOnClickListener(android.view.View.OnClickListener) to launch the provided RemoteResponse.void setPendingIntentTemplate(int viewId, PendingIntent pendingIntentTemplate)
When using collections (eg.void setProgressBar(int viewId, int max, int progress, boolean indeterminate)
Equivalent to calling ProgressBar#setMax, ProgressBar#setProgress, and ProgressBar#setIndeterminate If indeterminate is true, then the values for max and progress are ignored.void setRelativeScrollPosition(int viewId, int offset)
Equivalent to calling ListView#smoothScrollByOffset(int).void   setRemoteAdapter(int appWidgetId, int viewId, Intent intent)
This method was deprecated in API level 15. This method has been deprecated. See setRemoteAdapter(int, Intent)void  setRemoteAdapter(int viewId, Intent intent)
Equivalent to calling AbsListView.setRemoteViewsAdapter(Intent).void    setScrollPosition(int viewId, int position)
Equivalent to calling ListView#smoothScrollToPosition(int).void setShort(int viewId, String methodName, short value)
Call a method taking one short on a view in the layout for this RemoteViews.void    setString(int viewId, String methodName, String value)
Call a method taking one String on a view in the layout for this RemoteViews.void   setTextColor(int viewId, int color)
Equivalent to calling TextView.setTextColor(int).void   setTextViewCompoundDrawables(int viewId, int left, int top, int right, int bottom)
Equivalent to calling TextView#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int).void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom)
Equivalent to calling TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int).void setTextViewText(int viewId, CharSequence text)
Equivalent to calling TextView#setText(CharSequence)void    setTextViewTextSize(int viewId, int units, float size)
Equivalent to calling TextView#setTextSize(int, float)

上面很多set方法是通过反射来完成的。通过这些set方法可以对RemoteViews进行相关的操作:如:

void setTextViewText(int viewId, CharSequence text)
Equivalent to calling TextView#setText(CharSequence)void    setTextColor(int viewId, int color)
Equivalent to calling TextView.setTextColor(int).

用来设置TextView的文本和字体颜色。

RemoteViews主要用于通知栏和桌面小部件,所以分析他们的工作过程可以更具象化的了解RemoteViews的内部机制。通知栏和桌面小部件分别由NotificationManager和AppWidgetManager管理,它们通过Binder和系统服务进程中的NotificationManagerService和AppWidgetSetvice进行通信,通过这个可以看出来其实通知栏和桌面小部件的布局文件其实是在系统Service中加载并且运行在系统服务(SystemServer)中,这样我们应用中的进程就和系统进程组成了一个跨进程通信的场景了(关于跨进程通信有兴趣的小伙伴可以查看我之前写的两篇文章)
《Android 关于IPC机制的理解(一)》

《Android 关于IPC机制的理解(二)》

回到主题,查看源码我们发现RemoteViews实现了Parcelable接口,所以RemoteViews可以进行跨进程传输,而系统会通过构造RemoteViews时传递的包名去得到这个包名应用的资源文件,再通过LayoutInflater去加载构造时一起传递的布局文件。这个时候通过之前介绍的set方法提交的操作请求对view进行更新和操作。当RemoteViews加载完成之后RemoteViews就可以在SystemServer中显示。如果通知栏和小部件需要更新,就需要重新调用set方法,通过NotificationManager和AppWidgetManager来向SystemServer的相关Service提交更新任务了。


小结

这篇文章对RemoteViews的创建和工作流程进行了粗略说明,下一篇文章会从源码的角度对相关的内部机制流程进行分析。

Android 关于RemoteViews的理解(二)相关推荐

  1. Android 关于RemoteViews的理解(一)

    前言 RemoteViews从字面上理解是远程View,这个理解可能有点抽象,我们听过远程服务,但是远程View听说过的Android开发者应该很少,其实远程View和远程Service是一样的.谷歌 ...

  2. Android之RemoteViews篇上————通知栏和桌面小控件

    Android之RemoteViews篇上----通知栏和桌面小控件 一.目录 文章目录 Android之RemoteViews篇上----通知栏和桌面小控件 一.目录 二.RemoteViews的概 ...

  3. 【朝花夕拾】Android性能篇之(二)Java内存分配

    前言       原文:[朝花夕拾]Android性能篇之(二)Java内存分配        在内存方面,相比于C/C++程序员,咱们java系程序员算是比较幸运的,因为对于内存的分配和回收,都交给 ...

  4. 【转】Android菜单详解——理解android中的Menu--不错

    原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...

  5. Android菜单详解——理解android中的Menu

    前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至 ...

  6. android remoteviews 设置背景,Android通过RemoteViews实现跨进程更新UI示例

    一.概述 前面一篇文章Android通过AIDL实现跨进程更新UI我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新UI是可行的,但有以下弊端: View中的方法数比较多,在IPC中需要增加 ...

  7. Android openGl开发详解(二)

    https://zhuanlan.zhihu.com/p/35192609 Android openGl开发详解(二)--通过SurfaceView,TextureView,GlSurfaceView ...

  8. Android中RemoteViews的实现

    田海立@CSDN 2012-8-22 本文结合AppWidget的应用场景,分析Android中RemoteViews的内部具体实现. 从前文<Android中AppWidget的分析与应用:A ...

  9. Android 原生控件之二 ImageView

    Android 原生控件之二 ImageView 相关 来源 开始 XML属性 1.android:adjustViewBounds 2.android:baseline 3.android:base ...

最新文章

  1. CUDA硬件架构知识
  2. Hadoop企业优化
  3. 如何安装指定版本的 SAP Spartacus
  4. 链式栈的实现(头文件及源程序)
  5. 基于Echarts+HTML5可视化数据大屏展示—智慧社区内网对比平台
  6. tp php websocket教程,tp6 websocket方法详解
  7. 2021-02-18docker
  8. ue4 ui 序列图_UE4入门之路(UI篇):UMG系统介绍
  9. forward与sendRedirect区别
  10. 伙伴系统之避免碎片--Linux内存管理(十六)
  11. 顺丰速运和顺丰快递_携手快递外卖小哥,石浦交警送上“安全大礼包”
  12. mySQL数据库01
  13. 快手短视频运营实操技巧
  14. Word——永久修改默认标题和正文样式
  15. Leetcode 买卖股票的最佳时机
  16. IntelliJ IDEA 搭建网易云信IM服务端
  17. 程序员羊皮卷(张大志)pdf
  18. 【无标题】对WFM格式示波器图片打开问题
  19. PAT A1162 7-3 Summit (25分)
  20. python kafka库选择_【linux】安装python依赖库confluent_kafka

热门文章

  1. 网络编程之FTP文件传输协议
  2. 关于NetBios的简单应用
  3. Python爬取股票数据存入mysql数据库,获取股票(最新、最高、今开、成交量、成交额、量比、换手率、涨幅等)支持多线程+数据库连接池
  4. 在 Microsoft Word 插入代码块(无需下载任何软件)
  5. 第一章 1.3误差定性分析与避免误差危害
  6. Python+OpenCV图像处理与识别 Step by Step
  7. 国际物流专线是什么意思?
  8. hacker入门专业术语
  9. 微信小程序中数字取整
  10. 认识微型计算机系统结构实践报告,认识微机的主要部件实训报告.doc