最近在做车载launcher,把Launcher3修修改改之后放到车机上,bug非常多。
刚开始做的时候,大牛就说,最好自己写一个Launcher,launcher3移植到车机上很多bug,到时候改bug的时间都可以自己写一个Launcher了,很多bug真的很莫名其妙。
举个栗子:
在Launcher上加入默认排布,就是加载default_workspace.xml的时候,只加载默认排布的应用,其他应用都不加载了,我在手机上试过,是可以的,怎么在车机上就不行了。
当时就是觉得数据加载有问题了。
数据加载流程:在Launcher onCreate()的时候
if (!mRestoring) {
if (sPausedFromUserAction) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
mModel.startLoader(true, -1);
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
mModel.startLoader(true, mWorkspace.getCurrentPage());
}
}
调用了mModel.startLoader(true, -1);开始加载数据———
public void startLoader(boolean isLaunching, int synchronousBindPage) {
synchronized (mLock) {
if (DEBUG_LOADERS) {
Log.d(TAG, "startLoader isLaunching=" + isLaunching);
}
// Clear any deferred bind-runnables from the synchronized load process
// We must do this before any loading/binding is scheduled below.
mDeferredBindRunnables.clear();
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
Log.e("Launcher_debug", "Launcher_debug mCallbacks == " + mCallbacks);
// If there is already one running, tell it to stop.
// also, don't downgrade isLaunching if we're already running
isLaunching = isLaunching || stopLoaderLocked();
mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching);
if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {
Log.e("Launcher_debug", "Launcher_debug synchronousBindPage == " + synchronousBindPage);
mLoaderTask.runBindSynchronousPage(synchronousBindPage);
} else {
Log.e("Launcher_debug", "Launcher_debug mLoaderTask == " + mLoaderTask);
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
sWorker.post(mLoaderTask);
}
}
}
}
看到 mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching);
Log.e(“Launcher_debug”, “Launcher_debug mLoaderTask == ” + mLoaderTask);
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
sWorker.post(mLoaderTask);
这是把一个任务加入到线程,有线程那必须得看run()方法
public void run() {
boolean isUpgrade = false;
synchronized (mLock) {
mIsLoaderTaskRunning = true;
}
// Optimize for end-user experience: if the Launcher is up and // running with the
// All Apps interface in the foreground, load All Apps first. Otherwise, load the
// workspace first (default).
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 (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
Log.e("loadtask", "Load start''''''''");
isUpgrade = loadAndBindWorkspace();
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 (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
// Restore the default thread priority after we are done loading items
synchronized (mLock) {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
}
}
// Update the saved icons if necessary
if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
synchronized (sBgLock) {
for (Object key : sBgDbIconCache.keySet()) {
updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));
}
sBgDbIconCache.clear();
}
if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
// Ensure that all the applications that are in the system are
// represented on the home screen.
Log.e("Launcher", "Launcher_wan" + !UPGRADE_USE_MORE_APPS_FOLDER + !isUpgrade);
if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {
verifyApplications();
}
}
// 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;
}
bindWorkspace(-1, false);
}
在run()方法里面首先 isUpgrade = loadAndBindWorkspace(); load数据。
private boolean loadAndBindWorkspace() {
mIsLoadingAndBindingWorkspace = true;
Log.e("loadtask", "Load start''''''loadAndBindWorkspace''");
// Load the workspace
if (DEBUG_LOADERS) {
Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
}
boolean isUpgradePath = false;
Log.e("Launcher_debug", "Launcher_debug mWorkspaceLoaded == " + mWorkspaceLoaded);