Android Launcher构建之模型(LauncherModel.java)实现

来源:互联网 发布:大话西游2大圣附身数据 编辑:程序博客网 时间:2024/04/29 04:24

        基于MVC模型构建之Launcher系统,通过界面(VIEW)反应模型(MODEL)状态。同时所有需要被记录的用户与系统事件,最终都会交由模型来处理,以决定是改动到SQlite还是内部容器。在Launcher应用中模型需要完成的主要工作如下:

1.通过ContentProvider读取WorkSpace数据库排布设置

        WorkSpace用户排布需要存储到launcher.db,保证下次开机能回到先前的状态。通过ContentProvider将SQlite数据读写托管,模型端通过系统提供的ContentResolver解析读取到数据。launcher.db数据不存在则loadFavorites(db, R.xml.default_workspace)创建,存在则直接读取。
2.将workspace排布与APP信息写入状态容器。
         接下来就是将ContentResolver获取到的内容还原到XXXInfo(ShortcutInfo,LauncherAppWidgetInfo等),并根据ITEM_TYPE定义放入对应的影子容器中。但放入前必须使用checkItemPlacement 方法检验提取到的数据是否可以被放置,如无法放置将不出现在容器内。
3.利用状态容器内容构建用户界面。
       当图标位置信息加载完毕,接下来就是回调子类实现的interface Callbacks方法,UI线程开始添加对应的对象到界面。而launcher-loader线程将进入等待状态,直到界面排布完成才会被唤醒,接下来就是重复上面类似的流程加载AllApplist。对应到代码中的加载bind两步走:

//第一步加载WorkSpace,但需要执行部分都通过mHandler.post(new Runnable() 方法放到了主线程的延迟执行队列中。loadAndBindWorkspace();
//等待主线程空闲,调用this.wait();挂起了launcher-loader线程,UI线程执行Runnable.run单元,直到队列末尾的Idle单元并退出。waitForIdle();
//再次回到launcher-loader线程,准备并将需要UI线程执行的Bind部分放入延迟执行队列。loadAndBindAllApps();

4.处理来自系统的广播信息。
         因LauncherModel继承自BroadcastReceiver,那么他将具备处理系统广播的能力,入口为onReceive方法。即模型将负责监控与自身相关系统状态变化(APP卸载、安装、更新,用户配置修改,安装在SD卡上的应用状态,快速搜索图标状态等),接到系统通知后将修改影子容器,切换到UI线程对界面进行更新,最后由launcher-loader线程更新数据到存储设备。
5.界面用户操作修改同步到模型。
         当用户于界面上移动、添加、删除图标完成后,UI线程更新完成影子容器状态后将通知launcher-loader将状态更新到存储介质,这样的闭环保证了界面与模型内数据始终严格的一致。addOrMoveItemInDatabase是我们提供给出来的模型修改接口。
 
去除模型耦合度:
         对象耦合度最小,是增加可复用性与降低维护成本的好方法。模型在Launcher中的地位决定了他必须具备独立且高效两大能力,向下我们通过ContentProvider进行剥离,向上我们通过interface Callbacks将界面构建交给子类实现。
 
让模型更高效的执行:
          使用cache用空间换时间,多线程并发可提高系统效率。通过缓冲需要被界面使用与写入到SQlite中的数据可提高效率,我们分别使用了IconCache与java提供的ArrayList、HashMap(即影子容器)对常用的耗时数据进行缓冲。在模型中使用最频繁的线程为:UI主线程与launcher-loader线程。

原创粉丝点击