田海立@CSDN

2012-8-21

Launcher在Android的AppWidget整个体系中扮演AppWidgetHost的角色,本文分析Launcher对于AppWidget的处理,主要包括:选取AppWidgetProvider之后的处理;Launcher初始化过程中加载(包括第一次加载和之后正常的加载)AppWidget信息的处理,等。

由《Android中选取并绑定AppWidget》中知道,Launcher发起选取操作;Settings中的AppWidgetPickActivity获取所有已经安装的AppWidgetProvider,让用户选择,用户选择之后,回到启动它的Activity的onActivityResult()。

一、Launcher获取AppWidget之后的处理

先看Launcher中定义的用来处理AppWidget的相关的类:


图一、Launcher中AppWidget的相关类

  • Launcher是一个Activity;
  • 继承AppWidgetHost的LauncherAppWidgetHost用来操作AppWidgetHost功能,overrideonCreateView()用于创建自己的AppWidgetHostView– LauncherAppWidgetHostView;
  • LauncherAppWidgetHostView用来改变点击操作行为习惯;
  • Launcher把UserFolder/ LiveFolder / AppWidget等做成一定的数据模型,用ItemInfo来抽象,对应AppWidget用LauncherAppWidgetInfo来表达。

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


图二、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的更新。


图三、AppWidgetHost被更新

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

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


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

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


图四、Launcher的数据库操作LauncherProvider

  • Launcher在LauncherProvider中操作数据库;AppWidget相关项是在TABLE_FAVORITIES表单中;LauncherProvider.AUTHORITY定义操作数据库的入口,组合了LauncherSettings.Favorites.CONTENT_URI这个Uri来具体操作。
  • 用SQLite具体存储,所有用SQLiteOpenHelper的子类LauncherProvider.DatabaseHelper来具体操作SQLite数据库。
  • 数据库TABLE_FAVORITIES中的具体FiledLauncherSettings.Favorites中定义。

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


图五、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的配置:

<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指定的:

   <!-- XML attributes used by default_workspace.xml -->   <declare-styleable name="Favorite">       <attr name="className" format="string" />       <attr name="packageName" format="string" />       <attr name="screen" format="string" />       <attr name="x" format="string" />       <attr name="y" format="string" />       <attr name="spanX" format="string" />       <attr name="spanY" format="string" />       <attr name="icon" format="reference" />        <attr name="title" format="reference" />       <attr name="uri" format="string" />   </declare-styleable>

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

3.1 Launcher中的数据模型


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

  • LauncherModel是一个BroadcastReceiver;用mCallbacks记录Model变化时,要通知的对象;mAppWidgets中记录加入的AppWidget的信息。
  • Launcher实现LauncherModel.Callbacks,注册进LauncherModel,当Model变化时,做相应的处理。

3.2 Launcher数据模型的初始化


图七、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的工作。


图八、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


图九、Launcher bindAppwidget

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

总结

本文讲述了:

  • Launcher在选择了一个AppWidgetProvider之后,通过AppWidgetHost创建本地的AppWidgetHostView,用来呈现AppWidgetProvider通过RemoteViews提供的的提供内容。相应的LauncherAppWidgetInfo加入到LauncherModel的数据模型中。
  • Launcher(AppWidgetHost) / AppWidgetService /AppWidgetProvider由于运行于不同的进程中,执行的次序不确定使得RemoteViews的内容时效性不定,但是只要RemoteViews有更新,AppWidgetHost就会得到通知而更新。
  • 在系统第一次执行(刚烧机或恢复出厂设置之后)时,数据库第一次被初始化,会从default_workspace.xml中加载初始的AppWidget信息,并加入到LauncherModel的数据模型中。
  • 在正常开机过程(刚烧机或恢复出厂设置之后)中,AppWidget的信息被从数据库中读取出来,并加入到LauncherModel的数据模型中。

可进一步参考的文章

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

Android AppWidget框架

AppWidget系统框架。

Android中选取并绑定AppWidget

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

Android中AppWidget的分析与应用:AppWidgetProvider

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

Android中Launcher对于AppWidget处理的分析:AppWidgetHost角色

本文

Android中RemoteViews的实现

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

更多相关文章

  1. 打造android ORM框架opendroid(二)——自动创建数据库
  2. Gradle系列(四) Gradle插件
  3. Android中包含多个Activity的应用退出按钮实现
  4. Android简明开发教程九:创建应用程序框架
  5. Android读写XML(下)——创建XML文档
  6. Android学习系列之一
  7. Android(安卓)异步加载解决方案
  8. Android移动view动画问题 关于view的位置移动了,但view里面绑定的
  9. 【Android】异步加载解决方案

随机推荐

  1. AndFix解析——(上)
  2. 如何编程实现开启或者关闭GPS
  3. 构建 Android(安卓)手机 RSS 阅读器
  4. Android音乐播放器开发
  5. android中Invalidate和postInvalidate的
  6. Android之打造ListView的万能适配器
  7. Android数据库 之 SQLite数据库
  8. android service 详解
  9. Android高手进阶教程(十七)之---Android
  10. Android(安卓)图片缩放-Matrix