Android--launcher启动过程解析

第一步:我们先从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"); } }

当都加载完成以后会执行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); }

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


PS:这篇文章没有太多文字性的东西,关于代码的问题,请看代码注释,比较详细了。如果有疑问,欢迎留言探讨!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值