android launcher 升级,Android Launcher3分析——LauncherModel

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

接上篇Android Launcher3分析——开篇,上篇提到LauncherModel是Launcher3处理数据的核心,这当然不是瞎掰的,我们用具体的代码分析来予以佐证。

LauncherModel本身继承自BroadcastReceiver,实现了OnAppsChangedCallbackCompat接口,该接口在LauncherAppsCompat.java中定义,由LauncherModel中实现,并在LauncherAppsCompat子类的内部类PackageMonitor(API16以上)(继承BroadcastReceiver类型)或WrapperCallback(API15以下)调用,源码中关于LauncherModel的说明,大致含义如下:保持Launcher的内存状态。在内存静态区应该只能有一个LauncherModel的实例,同时它还为Launcher提供了一系列的更新数据库的Api。

内部类或接口

Callbacks(接口)

该接口定义了一些绑定数据时的具体方法,由Launcher实现,在LauncherModel中调用。

ItemInfoFilter(接口)

ItemInfo过滤器,过滤掉不符合条件的ItemInfo

LoaderTask(实现了Runnable接口)

核心内部类,主要任务负责加载数据(workspace、all apps)和绑定数据(workspace、all apps)

核心方法run1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39public void (){

synchronized (mLock) {

if (mStopped) {

return;

}

mIsLoaderTaskRunning = true;

}

keep_running:

{

if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");

loadAndBindWorkspace();

if (mStopped) {

break keep_running;

}

waitForIdle();

if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");

loadAndBindAllApps();

}

// Clear out this reference, otherwise we end up holding it until all of the

// callback runnables are done.

mContext = null;

synchronized (mLock) {

// If we are still the last one to be scheduled, remove ourselves.

if (mLoaderTask == this) {

mLoaderTask = null;

}

mIsLoaderTaskRunning = false;

mHasLoaderCompletedOnce = true;

}

}

先加载并绑定workspace,然后调用waitForIdle方法等待资源锁的释放,从而开始加载并绑定All Apps。在手动置空mContext(不然的话LoaderTask将持有mContext直至所有的runnable对象都被执行完毕,容易引起内存泄漏),接着指控LoaderTask本身,更新相关标识位。那么两个run里面的两个load函数到底有什么功能呢?

PackageUpdatedTask()

核心内部类, 实现了Runnable接口,主要负责更新Package信息(如package的增删改查等)

AppsAvailabilityCheck

BroadcastReceiver类型,根据包名检查对应app的有效性。

核心方法

loadAndBindWorkspace加载并绑定workspace,先加载后绑定;

loadWorkspace

loadWorkspace的代码实现较复杂,这里就不贴代码了,只根据代码做个简单的梳理:初始化必要的变量值,判断是否需要执行MigrateFromRestoreTask任务,根据mFlags判断是否需要对LauncherProvider中定义的数据库做初始化操作;

进入同步代码块:清空sBg的数据,使其恢复到初始化状态,定义用于接受清洗过后的数据的数据结构(itemsToRemove、restoreRows和occupied,这里的occupied指的就是Launcher桌面已经被Item占据的单元列表);

利用ContentResolver查询Favorites表,获取所有列的索引,以便后面根据对应索引去的对应列的值;

遍历Favorites表,根据ItemType对数据进行清洗:Application和Shortcut类型Item:将需要删除的item,需要移除的item,加入到对应的存储数据结构中,并将需要更新的item进行跟新操作

数据清洗完后,根据提供的条件,得到ShortcutInfo(最终展示在Launcher桌面上的那些图标),设置其属性(其中主要属性有intent(点击图标会对应的跳转操作),坐标(cellX,cellY)、占地面积(spanX,spanY),容纳图标的容器,所属的是哪一个屏幕等),这里还会根据container决定将当前item放入到什么位置(container为Workspace和Hotseat时,放入workspace中,其他情况放入Folder中

文档夹类型Item:设置folderInfo的属性,对于FolderInfo类型的Item,其本身位于容器Workspace之中,但又可以作为容器来承载(Application和Shortcut类Item)

设置完属性后,将其加入到对应的数据存储结构中,以便后面处理

Widget类型(自定义的或App提供的)根据对应的id机appWidgetId判断其有效性(将无效的加入到itemsToRemoved列表中,有效的则获取其appWidgetInfo信息);

移除不知道归属容器的Widget(就是不知道放哪儿的Widget)

更新providerName不一致的非自定义widget,然后将其加入到相应的数据结构;

处理清洗后的数据(itemsToRemoved、restoredRows等),这一步实质上是根据列表生成相应的sql语句,进行数据库操作;

移除空的屏幕,并更新。

以上就是loadWorkspace的全部过程,接下来看bindWorkspace时如何实现的。

bindWorkspace

由于bindWorkspace涉及到的都是UI操作,所以毫无疑问这些操作是在UI线程(即主线程)中完成的,具体实现方式是由LauncherModel调用Launcher实现的Callbacks接口里面的相应方法。bindWorkspace具体分析绑定前的准备工作(待使用的数据结构初始化,变量的初始化);

在主线程中解除当前已存在的items的绑定;

过滤数据,将要绑定的内容分为当前的和非当前的;

通知Launcher开始绑定

先绑定screen,在绑定item

通知Launcher所有绑定已完成

善后处理

loadAndBindAllApps

更新数据库的操作

主要包括对(App、App Shortcut、Widget、Folder的增删改查,具体体现在以下方法。addItemToDatabase,向数据库添加数据;

deletePackageFromDatabase,从数据库删除数据Package

deleteItemFromDatabase,从数据库删除Item

deleteItemsFromDatabase,从数据库批量删除item

deleteFolderContentsFromDatabase,从数据库删除文档夹里面的内容信息

moveItemInDatabase,更新Item的位置信息

moveItemsIndatabase,批量更新Item的位置信息

modifyItemInDatabase,更新Item的信息

updateItemInDatabase,更新Item的信息

总结

以上就是本人根据源码结合自己对Launcher3中的数据处理核心LauncherModel的粗陋分析,个人觉得值得借鉴的地方在于Callbacks的设计以及开始绑定之前的数据区分处理,当然个人觉得这里还是有不足之处的,那就是LauncherModel的loadWorkspace方法似乎太庞大了,如果自定义Launcher需要在这方面上进行优化。接下来会对Launcher3中的一些展示核心(自定义控件进行分析)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值