文章

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 及其子类中。通过 AppWidgetManagergetInstalledProvidersForProfile / getInstalledProvidersForPackage(Android 版本差异),获取到 AppWidgetProviderInfo 的集合。
  • LauncherAppWidgetHost 负责监听更新更新和创建 LauncherAppWidgetHostView。
  • LauncherAppWidgetHostView 扩展了 AppWidgetHostView,实现了对长按事件的处理。
  • LauncherAppWidgetHost 扩展了 AppWidgetHost,这里只是重载了 onCreateView,创建 LauncherAppWidgetHostView 的实例。

AppWidget 服务方(system_server)

  • AppWidgetService 是框架的的核心类,是系统 service 之一,它负责 widgets 的管理工作。加载,删除,定时事件等都需要 AppWidgetService 的处理。开机自启动的。
  • AppWidgetService 存在的目的主要是解开 AppWidgetProviderAppWidgetHost 之间的耦合。如果 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 进行授权