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

田海立@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 AppWidgetHost Class Diagram

图一、Launcher中AppWidget的相关类

 

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

 

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

Launcher AddAppWidget Sequence Diagram

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

Launcher updateAppWidget Sequence Diagram

图三、AppWidgetHost被更新

 

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

 

 

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


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

 

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

Launcher LauncherProvider Class Diagram

图四、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 LauncherProvider loadAppWidget Sequence Diagram

图五、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 Class Diagram

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

 

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

 

3.2 Launcher数据模型的初始化

 

Launcher LauncherModel constructor Sequence Diagram

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

 

Launcher LauncherModel LoadWorkspace BindWorkspace Sequence Diagram

图八、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 LauncherModel.Callbacks bindAppWidget Sequence Diagram

图九、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。

 

  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值