android ko加载流程,Android Launcher源码研究(三) 加载app流程2

接上次的。

首先Launcher实现了LauncherModel.Callbacks接口,APP信息数据加载成功后 ,回调接口把app信息显示到Launcher的 workspace界面上,这个过程代码里面称为bind。

下面是个类调用过程的时序图,不是很标准,不过能表达基本调用顺序帮助我们理解。

0ee728b83924b84bd276fb8433cd0c75.png

首先就是Launcher OnCreate中调用LauncherMode startLoader方法,这里只看异步的方式 就是当前的页面下标为-1,加载所有app信息

mWorkspace.getCurrentPage()为-1的情况。

mModel.startLoader(true, -1);

在LauncherMode类的startLoader方法里面,我们需要实例化线程类 LoaderTask,大部分工作都在这里面完成.

run方法的代码:

keep_running: {

// Elevate priority when Home launches for the first time to avoid

// starving at boot time. Staring at a blank home is not cool.

synchronized (mLock) {

if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +

(mIsLaunching ? "DEFAULT" : "BACKGROUND"));

android.os.Process.setThreadPriority(mIsLaunching

? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);

}

if (loadWorkspaceFirst) {

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

loadAndBindWorkspace();

} else {

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

loadAndBindAllApps();

}

if (mStopped) {

break keep_running;

}

// Whew! Hard work done. Slow us down, and wait until the UI thread has

// settled down.

synchronized (mLock) {

if (mIsLaunching) {

if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");

android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

}

}

waitForIdle();

// second step

if (loadWorkspaceFirst) {

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

loadAndBindAllApps();

} else {

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

loadAndBindWorkspace();

}

// Restore the default thread priority after we are done loading items

synchronized (mLock) {

android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);

}

}

我们定位到 loadAndBindWorkspace 方法 加载workspace界面

private void loadAndBindWorkspace() {

mIsLoadingAndBindingWorkspace = true;

// Load the workspace

if (DEBUG_LOADERS) {

Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);

}

if (!mWorkspaceLoaded) { //第一次加载

loadWorkspace(); //加载

synchronized (LoaderTask.this) {

if (mStopped) {

return;

}

mWorkspaceLoaded = true;

}

}

// Bind the workspace

bindWorkspace(-1);//绑定数据到UI

}

loadWorkspace方法就是加载手机里面的所有app信息,包括app widget, folder 并且存储到ArrayList中,后面显示这些东西到UI上。

数据我们存储好以后调用bindWorkspace(-1)开始显示数据到workspace,里面包含了很多调用方法,主要是数据排序,清除以前绑定的UI数据。

在bindWorkspace方法里面,调用了一些filter方法,这个地方主要是排序和过滤,分别判断需要加载到那个屏幕里面.

            r = new Runnable() {

public void run() {

Callbacks callbacks = tryGetCallbacks(oldCallbacks);

if (callbacks != null) {

callbacks.startBinding();//绑定之前,清理之前的数据,简单就这么理解

}

}

};

runOnMainThread(r);//UI更新需要在主线程中

下面这个方法就是把数据添加到workspace的屏幕中去.

bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,

currentFolders, null);

private void bindWorkspaceItems(final Callbacks oldCallbacks,

final ArrayList workspaceItems,

final ArrayList appWidgets,

final HashMap folders,

ArrayList deferredBindRunnables) {

final boolean postOnMainThread = (deferredBindRunnables != null);

// Bind the workspace items

int N = workspaceItems.size();

for (int i = 0; i < N; i += ITEMS_CHUNK) {

final int start = i;

final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);

final Runnable r = new Runnable() {

@Override

public void run() {

Callbacks callbacks = tryGetCallbacks(oldCallbacks);

if (callbacks != null) {

callbacks.bindItems(workspaceItems, start, start+chunkSize);//显示app信息到UI上

}

}

};

if (postOnMainThread) {

deferredBindRunnables.add(r);

} else {

runOnMainThread(r);

}

}

// Bind the folders

if (!folders.isEmpty()) {

final Runnable r = new Runnable() {

public void run() {

Callbacks callbacks = tryGetCallbacks(oldCallbacks);

if (callbacks != null) {

callbacks.bindFolders(folders);//显示folders

}

}

};

if (postOnMainThread) {

deferredBindRunnables.add(r);

} else {

runOnMainThread(r);

}

}

// Bind the widgets, one at a time

N = appWidgets.size();

for (int i = 0; i < N; i++) {

final LauncherAppWidgetInfo widget = appWidgets.get(i);

final Runnable r = new Runnable() {

public void run() {

Callbacks callbacks = tryGetCallbacks(oldCallbacks);

if (callbacks != null) {

callbacks.bindAppWidget(widget);//绑定AppWidget信息

}

}

};

if (postOnMainThread) {

deferredBindRunnables.add(r);

} else {

runOnMainThread(r);

}

}

}

我们这里只看第一个绑定shortcut信息代码,其他2个其实道理差不多.

public void bindItems(ArrayList shortcuts, int start, int end) {

setLoadOnResume();

// Get the list of added shortcuts and intersect them with the set of shortcuts here

Set newApps = new HashSet();

newApps = mSharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);

Workspace workspace = mWorkspace;

for (int i = start; i < end; i++) {

final ItemInfo item = shortcuts.get(i);

// Short circuit if we are loading dock items for a configuration which has no dock

if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&

mHotseat == null) {

continue;

}

switch (item.itemType) {

case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:

case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:

ShortcutInfo info = (ShortcutInfo) item;

String uri = info.intent.toUri(0).toString();

View shortcut = createShortcut(info);

workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,

item.cellY, 1, 1, false);

boolean animateIconUp = false;

synchronized (newApps) {

if (newApps.contains(uri)) {

animateIconUp = newApps.remove(uri);

}

}

if (animateIconUp) {

// Prepare the view to be animated up

shortcut.setAlpha(0f);

shortcut.setScaleX(0f);

shortcut.setScaleY(0f);

mNewShortcutAnimatePage = item.screen;

if (!mNewShortcutAnimateViews.contains(shortcut)) {

mNewShortcutAnimateViews.add(shortcut);

}

}

break;

case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:

FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,

(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),

(FolderInfo) item, mIconCache);

workspace.addInScreen(newFolder, item.container, item.screen, item.cellX,

item.cellY, 1, 1, false);

break;

}

}

workspace.requestLayout();

}

重点就是下面这个,把数据画到UI上面,坐标信息,APP信息.

workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,

item.cellY, 1, 1, false);

最后我们调用 finishBindingItems完成调用,这个方法里面还包括了滑动和显示APP动画方法的处理。

if (mVisible || mWorkspaceLoading) {

Runnable newAppsRunnable = new Runnable() {

@Override

public void run() {

runNewAppsAnimation(false);

}

};

boolean willSnapPage = mNewShortcutAnimatePage > -1 &&

mNewShortcutAnimatePage != mWorkspace.getCurrentPage();

if (canRunNewAppsAnimation()) {

// If the user has not interacted recently, then either snap to the new page to show

// the new-apps animation or just run them if they are to appear on the current page

if (willSnapPage) {

mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable);

} else {

runNewAppsAnimation(false);

}

} else {

// If the user has interacted recently, then just add the items in place if they

// are on another page (or just normally if they are added to the current page)

runNewAppsAnimation(willSnapPage);

}

}

详细的我们到后面继续分析。还包括具体Workspace上面的界面格子cell是怎么设计和APP添加位置的计算问题。

若有问题,请指出,谢谢~ O(∩_∩)O~

原文:http://blog.csdn.net/birdsaction/article/details/41515727

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值