展会信息港展会大全

Android--launcher启动过程解析
来源:互联网   发布日期:2016-01-06 19:23:45   浏览:3611次  

导读:第一步:我们先从LauncherApplication.java开始,先找到onCreate()方法:源码打印?publicvoidonCreate(){//设置最小堆内存8MVMRuntime.getRuntime().setMinimumHeapSize(8*1024*1024);//llxmodifytheheapsize......

第一步:我们先从LauncherApplication.java开始,先找到onCreate()方法:

源码打印?

public void onCreate() {

//设置最小堆内存8M

VMRuntime.getRuntime().setMinimumHeapSize(8 * 1024 * 1024); //llx modify the heapsize

super.onCreate();

//建立应用图标缓存器

mIconCache = new IconCache(this);

//建立LauncherModel

mModel = new LauncherModel(this, mIconCache);

// Register intent receivers

//注册Intent.ACTION_PACKAGE_ADDED,Intent.ACTION_PACKAGE_REMOVED,

//Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE,

//Intent.ACTION_LOCALE_CHANGED 事件监听器

//LauncherModel作为广播接收器对上面事件进行监听

IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);

filter.addAction(Intent.ACTION_PACKAGE_REMOVED);

filter.addAction(Intent.ACTION_PACKAGE_CHANGED);

filter.addDataScheme("package");

registerReceiver(mModel, filter);

filter = new IntentFilter();

filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);

filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);

registerReceiver(mModel, filter);

filter = new IntentFilter();

filter.addAction(Intent.ACTION_LOCALE_CHANGED);

registerReceiver(mModel, filter);

// Register for changes to the favorites

//添加对桌面favorites content provider 数据变化监听器

ContentResolver resolver = getContentResolver();

resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,mFavoritesObserver);

}

第二步:看下Launcher.java中的onCreate()方法:

源码打印?

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//获取LauncherApplication LauncherModel mIconCache等LauncherApplication初始化的对象

LauncherApplication app = ((LauncherApplication)getApplication());

mModel = app.setLauncher(this);

mIconCache = app.getIconCache();

//新建拖放控制器new DragController(this)

mDragController = new DragController(this);

mInflater = getLayoutInflater();

//获取桌面组件管理器,启动桌面组件host

mAppWidgetManager = AppWidgetManager.getInstance(this);

mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);

mAppWidgetHost.startListening();

if (PROFILE_STARTUP) {

android.os.Debug.startMethodTracing("/sdcard/launcher");

}

//从array.hotseats中加载所有的hotseats

loadHotseats();

//从加载本地设置

checkForLocaleChange();setWallpaperDimension();

//加载布局文件

setContentView(R.layout.launcher);

//初始化所有控件

setupViews();

registerContentObservers();

lockAllApps();

//从Bundle savedInstanceState获取桌面持久化数据

mSavedState = savedInstanceState;

restoreState(mSavedState);

if (PROFILE_STARTUP) {

android.os.Debug.stopMethodTracing();

}

if (!mRestoring) {

//LauncherModel.Loader.startLoader() 代码同步处理

mModel.startLoader(this, true);

}

// For handling default keys

mDefaultKeySsb = new SpannableStringBuilder();

Selection.setSelection(mDefaultKeySsb, 0);

//注册Intent.ACTION_CLOSE_SYSTEM_DIALOGS广播监听

IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

registerReceiver(mCloseSystemDialogsReceiver, filter);

}

第三步:加载桌面项: 在LauncherModel.java的Thread的run方法, 是在主线程完成以后才开始加载。

源码打印?

public void run() {

// 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).

final Callbacks cbk = mCallbacks.get();

final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;

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) {

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");

//从数据库launcher.db中查询中所有桌面项构造对应类型的ItemInfo对象存入

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) {

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();

}

}

这里调用了Launcher.java中startBinding方法

public void startBinding() {

final Workspace workspace = mWorkspace;

int count = workspace.getChildCount();

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

// Use removeAllViewsInLayout() to avoid an extra requestLayout() and invalidate().

((ViewGroup) workspace.getChildAt(i)).removeAllViewsInLayout();

}

if (DEBUG_USER_INTERFACE) {

android.widget.Button finishButton = new android.widget.Button(this);

finishButton.setText("Finish");

workspace.addInScreen(finishButton, 1, 0, 0, 1, 1);

finishButton.setOnClickListener(new android.widget.Button.OnClickListener() {

public void onClick(View v) {

finish();

}

});

}

}

还有Launcher.java的bindItem()方法:

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

setLoadOnResume();

//获取桌面的celllayout对象,也就是workspace下5个用户桌面中的一个

final Workspace workspace = mWorkspace;

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

//根据ItemInfo对象创建桌面图标view对象

final ItemInfo item = shortcuts.get(i);

mDesktopItems.add(item);

switch (item.itemType) {

case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:

case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:

final View shortcut = createShortcut((ShortcutInfo)item);

//获取item.screen, item.cellX, item.cellY, spanX, spanY并添加到屏幕上。

workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,false);

break;

case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:

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

(ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()),

(UserFolderInfo) item);

workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,false);

break;

case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:

final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(

R.layout.live_folder_icon, this,

(ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()),

(LiveFolderInfo) item);

workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,false);

break;

}

}

//.重新设置桌面图标view 的layoutparam(类型为cellLayout.layoutparam)

workspace.requestLayout();

}

注意,这两个方法都是异步调用。原因应该很清楚:时间。

另外还要注意一下两点:

1.桌面图标view对象添加OnLongClickListener=laucher,由laucher负责监听桌面图标view的longclick事件

2.如果桌面图标是DropTarget对象,拖放控制器mDragController添加该view到拖放目的地列表

在Launcher.java的代码中有bindFolders()和bindAppWidget()方法,都是回调方法。主要看下bindAppWidget()方法吧。

/**

* Add the views for a widget to the workspace.

*

* Implementation of the method from LauncherModel.Callbacks.

*/

public void bindAppWidget(LauncherAppWidgetInfo item) {

setLoadOnResume();

final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;

if (DEBUG_WIDGETS) {

Log.d(TAG, "bindAppWidget: " + item);

}

final Workspace workspace = mWorkspace;

//获取LauncherAppWidgetInfo的appWidgetId

final int appWidgetId = item.appWidgetId;

//根据appWidgetInfo创建桌面组件的view AppWidgetHostView对象

final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

if (DEBUG_WIDGETS) {

Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);

}

item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);

item.hostView.setAppWidget(appWidgetId, appWidgetInfo);

item.hostView.setTag(item);

//添加到对应桌面的cell

workspace.addInScreen(item.hostView, item.screen, item.cellX,

item.cellY, item.spanX, item.spanY, false);

workspace.requestLayout();

mDesktopItems.add(item);

if (DEBUG_WIDGETS) {

Log.d(TAG, "bound widget id="+item.appWidgetId+" in "

+ (SystemClock.uptimeMillis()-start) + "ms");

}

}

<span style="font-size:16px;">

</span>

当都加载完成以后会执行finishBindingItems():

/**

* Callback saying that there aren't any more items to bind.

*

* Implementation of the method from LauncherModel.Callbacks.

*/

public void finishBindingItems() {

setLoadOnResume();

if (mSavedState != null) {

if (!mWorkspace.hasFocus()) {

mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();

}

final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);

if (userFolders != null) {

for (long folderId : userFolders) {

final FolderInfo info = sFolders.get(folderId);

if (info != null) {

openFolder(info);

}

}

final Folder openFolder = mWorkspace.getOpenFolder();

if (openFolder != null) {

openFolder.requestFocus();

}

}

mSavedState = null;

}

if (mSavedInstanceState != null) {

super.onRestoreInstanceState(mSavedInstanceState);

mSavedInstanceState = null;

}

mWorkspaceLoading = false;

}

前面那三个都是都是回调方法,控制器当然是LauncherModel.java了,让我们在代码里看一下:

其接口定义如下:

public interface Callbacks {

public boolean setLoadOnResume();

public int getCurrentWorkspaceScreen();

public void startBinding();

public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end);

public void bindFolders(HashMap<Long,FolderInfo> folders);

public void finishBindingItems();

public void bindAppWidget(LauncherAppWidgetInfo info);

public void bindAllApplications(ArrayList<ApplicationInfo> apps);

public void bindAppsAdded(ArrayList<ApplicationInfo> apps);

public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);

public void bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent);

public boolean isAllAppsVisible();

}

想看仔细的,自己可以在代码中找一下。

最后执行 bindAllApplications() , bindAppsAdded()方法:

public void bindAllApplications(ArrayList<ApplicationInfo> apps) {

mAllAppsGrid.setApps(apps);

}

/**

* A package was installed.

*

* Implementation of the method from LauncherModel.Callbacks.

*/

public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {

setLoadOnResume();

removeDialog(DIALOG_CREATE_SHORTCUT);

mAllAppsGrid.addApps(apps);

}

到这基本上就是整个的启动过程了。

赞助本站

人工智能实验室

相关热词: launcher启动过程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港