android 进lanucher的广播,(转)Android中Launcher对于AppWidget处理的分析:AppWidgetHost角色...

图二的时序图描述了,从AppWidgetPickActivity返回之后,Launcher如何处理AppWidget的。

a4c26d1e5885305701be709a3d33442f.png

图二、Picked之后Launcher对AppWidget的处理

执行过程:

1. onActivityResult()中,从requestCode以及resultCode里知道,选取AppWidget成功,可以从返回的data:Intent中获得appWidgetId;[Seq#1]

2. 通过AppWidgetId获得info:

AppWidgetProviderInfo;[Seq#5~ #6]

3. 创建LauncherAppWidgetInfo的实例,并加入到数据模型LauncherModel中;[Seq#7]

4. 通过LauncherAppWidgetHost.createView()创建AppHostView;[Seq#8~

#15]

由于override里onCreateView(),onCreateView()被执行。在onCreateView()中创建LauncherAppWidgetHostView;[Seq#8~

#10]

AppWidgetHost.createView()中,把AppWidgetProviderInfo设置到appWidgetHostView里;[Seq#11]

AppWidgetHost.createView()中,通过AppWidgetService获得AppWidgetProvider提供的RemoteViews【AppWidgetHost、AppWidgetProvider、AppWidgetService运行在不同的进程中,此时不能保证RemoteViews有内容,亦即不能保证AppWidgetProvider.onUpdate()已经被执行】;[Seq#12~

#13]

AppWidgetHost.createView()中,用RemoteViews更新appWidgetHostView;[Seq#14]

返回已创建AppWidgetHostView的实例;[Seq#15]

5. 向AppWidgetHostView里设置TAG

– LauncherAppWidgetInfo的实例。[Seq#17]

最后,LauncherAppWidgetHostView被加入到当前屏,让相应的显示部分来完成显示。因为此时RemoteViews里可能还没有内容,这里只是用一定的占空在Workspace中先占一定的空间。

当AppWidgetProvider获得更新的广播,并执行onUpdate(),onUpdate()中创建了RemoteViews并通过AppWidgetManager.updateAppWidget()更新到AppWidgetService之后,AppWidgetService会通过注册的IAppWidgetHost的回调,执行AppWidgetHost的更新。

a4c26d1e5885305701be709a3d33442f.png

图三、AppWidgetHost被更新

《Android中RemoteViews的实现》中的Section#3讲述了RemoteViews后续的处理。

Launcher在初始化过程中,还会根据配置在第一次创建Database时把AppWidget加载进来;不是第一次创建时,把数据库中的AppWidget的内容Load到数据模型中。

二、Launcher第一次创建Database时,处理AppWidget

Launcher的数据库操作的相关的类

a4c26d1e5885305701be709a3d33442f.png

图四、Launcher的数据库操作LauncherProvider

Launcher在LauncherProvider中操作数据库;AppWidget相关项是在TABLE_FAVORITIES表单中;LauncherProvider.AUTHORITY定义操作数据库的入口,组合了LauncherSettings.Favorites.CONTENT_URI这个Uri来具体操作。

用SQLite具体存储,所有用SQLiteOpenHelper的子类LauncherProvider.DatabaseHelper来具体操作SQLite数据库。

数据库TABLE_FAVORITIES中的具体Filed在LauncherSettings.Favorites中定义。

Launcher第一次创建数据库时,LauncherProvider.DatabaseHelper.onCreate()会被执行,对AppWidget的处理如下:

a4c26d1e5885305701be709a3d33442f.png

图五、Launcher第一次创建数据库时,对AppWidget的处理

执行过程:

1. 移除掉Launcher作为AppWidgetHost相关的内容;[Seq#4]

2. 解析default_workspace.xml中的内容,如果是appwidget相关的:

a) 申请AppWidgetId;[Seq#8

~ #9]

b) 把解析出的内容插入TABLE_FAVORITES表单;[Seq#10]

c) 把AppWidgetId与AppWidgetProvider绑定;[Seq#11]

其实这个过程就浓缩了用户选择AppWidgetProvider,然后再绑定等等一系列的过程。只是这里的要用哪个AppWidgetProvider,放在哪一屏的哪个位置都在配置里确定了,所以可以直接自动完成。

比如,下面是res/xml/default_workspace.xml中,关于“电量控制”这个AppWidget的配置:

launcher:packageName="com.android.settings"

launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"

launcher:screen="3"

launcher:x="0"

launcher:y="0"

launcher:spanX="4"

launcher:spanY="1"/>

而要解析default_workspace.xml中AppWidget的哪些属性是由res/values/attrs.xml中的Favorite指定的:

三、Launcher正常启动加载数据库中的AppWidget

3.1 Launcher中的数据模型

a4c26d1e5885305701be709a3d33442f.png

图六、Launcher中的简要数据模型

LauncherModel是一个BroadcastReceiver;用mCallbacks记录Model变化时,要通知的对象;mAppWidgets中记录加入的AppWidget的信息。

Launcher实现LauncherModel.Callbacks,注册进LauncherModel,当Model变化时,做相应的处理。

3.2 Launcher数据模型的初始化

a4c26d1e5885305701be709a3d33442f.png

图七、Launcher数据模型的初始化

执行顺序:

1. Launcher被创建时,Launcher.onCreate()被执行;

2. 通过getApplication()获得LauncherApplication;LauncherApplication被创建(launcherApplication.onCreate())时:

a) 实例化LauncherModel,并把LauncherApplication自身传进去;

b) 为LauncherModel注册广播;

3. 通过LauncherApplication的setLauncher()把Launcher自身传进去;

LauncherApplication.

setLauncher()调用LauncherModel的initialize()把Launcher这个launcherModel.Callbacks的实例传进去;

4. 实例化LauncherAppWidgetHost这个AppWidgetHost,并通过startListening(),把IAppWidgetHost注册进AppWidgetSerivce。

3.3 加载并绑定Workspace

在需要加载数据模型的时,LauncherModel的startLoader()会被执行。LauncherModel开启一个LoaderTask线程,具体执行load和bind的工作。

a4c26d1e5885305701be709a3d33442f.png

图八、LauncherModel加载并绑定Workspace

执行加载过程:

1. 用LauncherSettings.Favorites.CONTENT_URI查询所有的数据;[Seq#1~

#3]

2. 从LauncherSettings.Favorites.ITEM_TYPE字段获取当前记录的类型;[Seq#4~

#7]。

3. 对于AppWidget类型(type为LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET),获得AppWidget关注的其他字段,并赋值给LauncherAppWidgetInfo;[Seq#8~

#9]

4. 把LauncherAppWidgetInfo的实例加入mAppWidgets;[Seq#10]

执行绑定过程:

通过LauncherModel.Callbacks的实现,也就是Launcher,执行:

startBinding();

对所有的mAppWidgets中的Widget,执行bindAppWidget()。

执行LauncherModel.Callbacks.bindAppWidget()在Launcher中执行。

3.4 Launcher绑定AppWidget

a4c26d1e5885305701be709a3d33442f.png

图九、Launcher bindAppwidget

这个过程同图二的执行,可参考研读。

总结

本文讲述了:

Launcher在选择了一个AppWidgetProvider之后,通过AppWidgetHost创建本地的AppWidgetHostView,用来呈现AppWidgetProvider通过RemoteViews提供的的提供内容。相应的LauncherAppWidgetInfo加入到LauncherModel的数据模型中。

Launcher(AppWidgetHost) / AppWidgetService

/AppWidgetProvider由于运行于不同的进程中,执行的次序不确定使得RemoteViews的内容时效性不定,但是只要RemoteViews有更新,AppWidgetHost就会得到通知而更新。

在系统第一次执行(刚烧机或恢复出厂设置之后)时,数据库第一次被初始化,会从default_workspace.xml中加载初始的AppWidget信息,并加入到LauncherModel的数据模型中。

在正常开机过程(非刚烧机或恢复出厂设置之后)中,AppWidget的信息被从数据库中读取出来,并加入到LauncherModel的数据模型中。

可进一步参考的文章

通过这一系列的其他文章,可获得与本文关联的信息:

AppWidget系统框架。

Launcher发起选取过程,此文中描述选取并绑定的过程,可结合本文看完整的选取/绑定/加入显示系统的完整过程。

本文所描述的信息,是此文所描述的AppWodgetProvider所提供的。

本文

RemoteViews的内部如何实现,看如何具体用RemoteViewsupdate AppWidgetHostView。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值