05. App Widget原理
05. App Widget原理
App Widget 原理
AppWidget 提供方(App)
你自己开发的 app
AppWidgetProvider
- xml 用
<appwidget-provider>
定义 - 重写
AppWidgetProvider
的一些方法 - AppWidgetProvider 的使用经验
- 作为 AppWidgetProvider 的实现者,一定要实现 onUpdate 函数,因为这个函数决定 widget 的显示方式,如果没有这个函数 widget 根本没办法出现。
- onUpdate 的实现基本上遵循下面的流程:
- 创建 RemoteViews。
- 调用 AppWidgetManager 的 updateAppWidget 去更新 widget。
AppWidget 显示方(Launcher)
一般是 Launcher
AppWidgetHost
AppWidgetHost 是实际控制 widget 的地方,要注意,widget 不是一个单独的用户界面程序,他必须寄生在某个程序(activity)中,这样如果程序要支持 widget 寄生就要实现 AppWidgetHost。它的主要功能有两个:
- 监听来自
AppWidgetService
的事件 - 创建
AppWidgetHostView
RemoteViews 不是真正的 View,只是 View 的描述,而 AppWidgetHostView 才是真正的 View。这里先创建 AppWidgetHostView,然后通过 AppWidgetService 查询 appWidgetId 对应的 RemoteViews,最后把 RemoteViews 传递给 AppWidgetHostView 去 updateAppWidget。
AppWidgetHost 和 AppWidgetHostView 是在框架中定义的两个基类。应用程序可以利用这两个类来实现自己的 Host。Launcher 是缺省的桌面,它是一个 Host 的实现者。
AppWidgetHostView 是真正的 View,但它只是一个容器,用来容纳实际的 AppWidget 的 View。这个 AppWidget 的 View 是根据 RemoteViews 的描述来创建。
Launcher3 对 Widget 的支持
- Launcher3 对所有 widget 的遍历是在
AppWidgetManagerCompat
及其子类中。通过AppWidgetManager
的getInstalledProvidersForProfile
/getInstalledProvidersForPackage
(Android 版本差异),获取到AppWidgetProviderInfo
的集合。 LauncherAppWidgetHost
负责监听更新更新和创建 LauncherAppWidgetHostView。LauncherAppWidgetHostView
扩展了 AppWidgetHostView,实现了对长按事件的处理。LauncherAppWidgetHost
扩展了 AppWidgetHost,这里只是重载了 onCreateView,创建 LauncherAppWidgetHostView 的实例。
AppWidget 服务方(system_server)
- AppWidgetService 是框架的的核心类,是系统 service 之一,它负责 widgets 的管理工作。加载,删除,定时事件等都需要 AppWidgetService 的处理。开机自启动的。
- AppWidgetService 存在的目的主要是解开
AppWidgetProvider
和AppWidgetHost
之间的耦合。如果 AppWidgetProvider 和 AppWidgetHost 的关系固定死了,AppWidget 就无法在任意进程里显示了。而有了 AppWidgetService,AppWidgetProvider 根本不需要知道自己的 AppWidget 在哪里显示了。 - AppWidgetManager 负责 widget 视图的实际更新以及相关管理。
小结
App Widget 时序
- AppWidgetService 启动:SystemServer 服务,开机启动。
- AppWidgetProviderInfo 获取:AppWidgetService 通过 PMS 针对注册了
ACTION_APPWIDGET_UPDATE
(”android.appwidget.action.APPWIDGET_UPDATE
“)的静态广播进行扫描查询。 - meta-data 解析:查询到的就是 AppWidget,然后从其配置的 meta-data 中的 “appwidget-provider” 对应的 xml 文件开始解析生成 AppWidgetProviderInfo 结构体。
- Launcher3 获取 Widget 信息:Launcher 通过 AppWidgetManager 向 AppWidgetService 按需拿到所有的 AppWidget 信息,可以进行展示。
- Launcher3 显示 Widget 信息:Launcher 创建 AppWidgetHost,通过上面拿到的 Widget 信息生成对应的 AppWidgetHostView 进行展示。
- Launcher3 更新 Widget 信息:AppWidgetHost 创建监听 AppWidgetService 的更新,进行接收回调显示更新。
- AppWidget 被动刷新:AppWidgetService 会根据 AppWidgetProviderInfo 的配置维持一个 30 分钟下限的更新时钟,来给 AppWidgetProvider 来发送更新通知。
- AppWidget 主动刷新:应用侧可以拿到 AppWidgetManager 来进行主动刷新。
AppWidget 的更新过程
- Widget 更新:提供方把应用信息 + RemoteViews 包装好发给发给服务方(这些只是信息结构体,其实并不是 View),显示方监听从服务方的回调,在回调中可以拿到这些信息结构体。
- 理解方式:虽然我们的目的是更新 View,但是我们不能用更新 View 的思路去理解,只能用更新 Data 的思路去理解。
- 更新频繁不好,因为虽然在应用提供方不涉及 View 的频繁加载,但是在显示方(要通过数据结构生成 View),这就是系统原生为什么把 AppWidget 的被动刷新频率下限设定为半小时。
本文由作者按照 CC BY 4.0 进行授权