日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android4.0源码Launcher启动流程分析【android源码Launcher系列一】

發布時間:2025/7/14 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android4.0源码Launcher启动流程分析【android源码Launcher系列一】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? 最近研究ICS4.0的Launcher,發現4.0和2.3有稍微點區別,但是區別不是特別大,所以我就先整理一下Launcher啟動的大致流程。 Launcher其實是貫徹于手機的整個系統的,時時刻刻都在運行,要是Launcher不運行了,手機就得黑屏了。Launcher的 LauncherMode=singletask,所以說不管Launcher啟動了哪個應用,總有個Launcher的實例在堆棧中,并且位于棧底。點 擊Home鍵進入到Launcher,上篇Android的全局鍵(home鍵/長按耳機鍵)詳解【android源碼解析八】?中有詳細的介紹。大致思路其實就是啟動launcher的時候,新啟動一個task。大致先說這么多,先看截圖:

?

?

?????????????????????????????????????

?

?????????????????????????????????????????????????????????????????????????? 圖(1)

????? 上圖是4.0的Launcher界面,下面我們分步來解析一下Launcher的啟動過程。

?

???? Step 0:首先要給大家介紹一下Launcher的數據庫,這個數據庫中存放著待機界面的圖標,主屏底部的應用程序圖標和桌面folder中各應用程序的圖 標,ICS4.0的folder中只能放應用程序的快捷方式,shortcut不能放到這個folder中,先看截圖:?



?

??????????????????????????????????????????????????????????????????????? 圖(2)

????? ?說說各字段的含義:

??????????????? title:表示桌面應用程序的名字,有的title為空,表示是widget的快捷方式;

?????????????intent:表示啟動這個圖標的intent放到數據庫中,當click的時候就會調用這個字段,啟動相應的應用程序;

???????container:表示應用程序的容器,folder的容器為整數,-100:表示在桌面的程序,-101:表示是主屏底部的程序;

???????????screen:表示在第幾個屏,folder的screen都是0, container=-101的為0,1,3,4;2為allapp的按鈕;

?????????????? cellX:表示在屏幕X軸的位置,(0,1,2,3),左上角為0點,往右依次增加;

???????????????cellY:表示在屏幕Y軸的位置,(0,1,2,3),左上角為0點,往下依次增加;

????????????? spallX:表示占X軸幾個格;

????????????? spallY:表示占Y軸幾個格;

???????? itemType:應用程序用0表示,shortcut用1表示,folder用2表示,widget用4表示;

??? appWidgetId:-1表示不是widget,數字大于0表示才是widget;

???????isShortCut:值為0表示不是應用程序的ShortCut,值為1表示是應用程序的ShortCut;

???????? iconType:值為0表示圖標的名字被定義為包名的資源id,值為1表示圖標用bitmap保存;

???????????????? icon:表示應用程序的圖標,二進制的;顯示為一張圖片;

?????? 說明:folder中的應用快捷方式綁定folder---->是用container的值綁定folder的id的;

??????? 詳細的講解請參考LauncherSettings.java這個類,有數據庫字段的詳細講解;

?????????手 機是在第一次燒機完成后,數據庫的值還沒有,這時候launcher解析default_workspace.xml把這個值存到數據庫中;所以說想定制 什么樣的開機桌面就在default_workspace.xml中做相應的配置,具體參照我前面的博客:

Android中源碼Launcher主屏幕程序排列詳解【安卓Launcher進化一】中有詳細的介紹:

?????? i f (!convertDatabase(db))?{
??????????????? ?// Populate favorites table with initial favorites
??????????????? loadFavorites(db, R.xml.default_workspace);
????????}

?

??????Step?1:開機后先啟動LauncherApplication.java這個類的onCreate()方法,下面看代碼:???

???

Java代碼??
  • @Override??
  • ?public?void?onCreate()?{??
  • ?????super.onCreate();??
  • ??
  • ?????//?set?sIsScreenXLarge?and?sScreenDensity?*before*?creating?icon?cache??
  • ?????//?在創建圖標緩存之前先設置sIsScreenXLarge和屏幕設備的分辨率??
  • ?????final?int?screenSize?=?getResources().getConfiguration().screenLayout?&??
  • ?????????????Configuration.SCREENLAYOUT_SIZE_MASK;??
  • ?????sIsScreenLarge?=?screenSize?==?Configuration.SCREENLAYOUT_SIZE_LARGE?||??
  • ?????????screenSize?==?Configuration.SCREENLAYOUT_SIZE_XLARGE;??
  • ?????sScreenDensity?=?getResources().getDisplayMetrics().density;??
  • ??
  • ?????//?實例化圖標緩存區的對象??
  • ?????mIconCache?=?new?IconCache(this);??
  • ?????//?實例化一個LauncherModel對象,這個類是保存Launcher的內存啟動狀態,更新Launcher的數據庫的作用??
  • ?????mModel?=?new?LauncherModel(this,?mIconCache);??
  • ??
  • ?????//?Register?intent?receivers??
  • ?????//?注冊監聽,應用package增加,刪除,改變的監聽。??
  • ?????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();??
  • ?????//?注冊application是否可用,語言改變,方向改變的監聽。4.0支持橫豎屏??
  • ?????filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);??
  • ?????filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);??
  • ?????filter.addAction(Intent.ACTION_LOCALE_CHANGED);??
  • ?????filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);??
  • ?????registerReceiver(mModel,?filter);??
  • ?????filter?=?new?IntentFilter();??
  • ?????filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);??
  • ?????registerReceiver(mModel,?filter);??
  • ?????filter?=?new?IntentFilter();??
  • ?????filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);??
  • ?????registerReceiver(mModel,?filter);??
  • ??
  • ?????//?Register?for?changes?to?the?favorites??
  • ?????//?注冊favorites應用程序數據庫改變的監聽??
  • ?????ContentResolver?resolver?=?getContentResolver();??
  • ?????resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI,?true,??
  • ?????????????mFavoritesObserver);??
  • ?}??
  • ?

    ???????Step 2:在LauncherApplication.java中onTerminate()的方法,解除監聽的綁定;

    ?

    Java代碼??
  • /**?
  • ????*?There's?no?guarantee?that?this?function?is?ever?called.?
  • ????*/??
  • ???@Override??
  • ???public?void?onTerminate()?{??
  • ???????super.onTerminate();??
  • ??
  • ???????unregisterReceiver(mModel);??
  • ??
  • ???????ContentResolver?resolver?=?getContentResolver();??
  • ???????resolver.unregisterContentObserver(mFavoritesObserver);??
  • ???}??
  • ?

    ???? Step 3:Step1中的數據庫mFavoritesObserver監聽內部類如下:

    ?

    Java代碼??
  • /**?
  • ??*?Receives?notifications?whenever?the?user?favorites?have?changed.?
  • ??*/??
  • ?private?final?ContentObserver?mFavoritesObserver?=?new?ContentObserver(new?Handler())?{??
  • ?????@Override??
  • ?????public?void?onChange(boolean?selfChange)?{??
  • ?????????mModel.startLoader(LauncherApplication.this,?false);??
  • ?????}??
  • ?};??
  • ?

    說明:mModel.startLoader(。。,。。)是開啟一個線程,設置線程的優先級NORM_PRIORITY,開始load桌面圖標對應的數據庫,這個過程是和Launcher.onCreate()同時進行的;

    ????Step 4: 接著我們來看看mModel.startLoader(LauncherApplication.this, false)的方法:

    ?

    Java代碼??
  • public?void?startLoader(Context?context,?boolean?isLaunching)?{??
  • ?????synchronized?(mLock)?{??
  • ?????????if?(DEBUG_LOADERS)?{??
  • ?????????????Log.d(TAG,?"startLoader?isLaunching="?+?isLaunching);??
  • ?????????}??
  • ??
  • ?????????//?Don't?bother?to?start?the?thread?if?we?know?it's?not?going?to?do?anything??
  • ?????????if?(mCallbacks?!=?null?&&?mCallbacks.get()?!=?null)?{??
  • ?????????????//?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(context,?isLaunching);??
  • ?????????????sWorkerThread.setPriority(Thread.NORM_PRIORITY);??
  • ?????????????sWorker.post(mLoaderTask);??
  • ?????????}??
  • ?????}??
  • ?}??
  • ??

    ?? Step 5:接著我們來看看LoaderTask.java的run()方法:

    Java代碼??
  • 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)?{??
  • ????????????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);??
  • ????????}??
  • ????}??
  • ??
  • ??
  • ????//?Update?the?saved?icons?if?necessary??
  • ????if?(DEBUG_LOADERS)?Log.d(TAG,?"Comparing?loaded?icons?to?database?icons");??
  • ????for?(Object?key?:?sDbIconCache.keySet())?{??
  • ????????updateSavedIcon(mContext,?(ShortcutInfo)?key,?sDbIconCache.get(key));??
  • ????}??
  • ????sDbIconCache.clear();??
  • ??
  • ????//?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;??
  • ????????}??
  • ????}??
  • }??
  • ??
  • public?void?stopLocked()?{??
  • ????synchronized?(LoaderTask.this)?{??
  • ????????mStopped?=?true;??
  • ????????this.notify();??
  • ????}??
  • }??
  • ?

    加載桌面圖標對應的數據庫的值,這些值能把這些圖標顯示在屏幕上。

    ?

    ?

    ??? Step 6:LauncherApplication.onCreate()方法啟動完成后,接著開始調用Launcher.java的onCreate()方法。代碼如下:

    Java代碼??
  • @Override??
  • protected?void?onCreate(Bundle?savedInstanceState)?{??
  • ????super.onCreate(savedInstanceState);??
  • ????//?得到LauncherApplication的對象app??
  • ????LauncherApplication?app?=?((LauncherApplication)getApplication());??
  • ????//?得到LauncherModel對象mModel,設置一個mCallbacks?=?new?WeakReference<Callbacks>(callbacks)的??
  • ????//?回調callbacks??
  • ????mModel?=?app.setLauncher(this);??
  • ????//?得到圖標緩存的對象mIconCache??
  • ????mIconCache?=?app.getIconCache();??
  • ????//?得到拖拽控制類DragController的對象??
  • ????mDragController?=?new?DragController(this);??
  • ????//?得到一個LayoutInflater布局的對象??
  • ????mInflater?=?getLayoutInflater();??
  • ??
  • ????//?得到一個AppWidgetManager的對象??
  • ????mAppWidgetManager?=?AppWidgetManager.getInstance(this);??
  • ????//?得到LauncherAppWidgetHost的一個對象??
  • ????mAppWidgetHost?=?new?LauncherAppWidgetHost(this,?APPWIDGET_HOST_ID);??
  • ????//?Start?receiving?onAppWidgetChanged?calls?for?your?AppWidgets.??
  • ????mAppWidgetHost.startListening();??
  • ??
  • ????if?(PROFILE_STARTUP)?{??
  • ????????android.os.Debug.startMethodTracing(??
  • ????????????????Environment.getExternalStorageDirectory()?+?"/launcher");??
  • ????}??
  • ??
  • ????//?檢查Locale的語言級別,mcc,?mnc的改變??
  • ????checkForLocaleChange();??
  • ????//?加載Launcher.xml布局文件??
  • ????setContentView(R.layout.launcher);??
  • ????//?Launcher的布局的初始化??
  • ????setupViews();??
  • ????//?第一次啟動Android的展示設置向導,??
  • ????//?這個SharedPreferences中存在??
  • ????//?<boolean?name="cling.workspace.dismissed"?value="true"?/>??
  • ????//?如果值為true,則不顯示設置向導,為false,則顯示設置向導。??
  • ????showFirstRunWorkspaceCling();??
  • ??
  • ????//?注冊數據庫觀察者??
  • ????registerContentObservers();??
  • ??
  • ????lockAllApps();??
  • ??
  • ????mSavedState?=?savedInstanceState;??
  • ????restoreState(mSavedState);??
  • ??
  • ????//?Update?customization?drawer?_after_?restoring?the?states??
  • ????if?(mAppsCustomizeContent?!=?null)?{??
  • ????????mAppsCustomizeContent.onPackagesUpdated();??
  • ????}??
  • ??
  • ????if?(PROFILE_STARTUP)?{??
  • ????????android.os.Debug.stopMethodTracing();??
  • ????}??
  • ??
  • ????if?(!mRestoring)?{??
  • ????????mModel.startLoader(this,?true);??
  • ????}??
  • ??
  • ????if?(!mModel.isAllAppsLoaded())?{??
  • ????????ViewGroup?appsCustomizeContentParent?=?(ViewGroup)?mAppsCustomizeContent.getParent();??
  • ????????mInflater.inflate(R.layout.apps_customize_progressbar,?appsCustomizeContentParent);??
  • ????}??
  • ??
  • ????//?For?handling?default?keys??
  • ????mDefaultKeySsb?=?new?SpannableStringBuilder();??
  • ????Selection.setSelection(mDefaultKeySsb,?0);??
  • ??
  • ????//?注冊系統對話框消失的監聽??
  • ????IntentFilter?filter?=?new?IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);??
  • ????registerReceiver(mCloseSystemDialogsReceiver,?filter);??
  • ??
  • ????boolean?searchVisible?=?false;??
  • ????boolean?voiceVisible?=?false;??
  • ????//?If?we?have?a?saved?version?of?these?external?icons,?we?load?them?up?immediately??
  • ????//?如果我們已經保存了外部圖標的版本,我們立即加載它們??
  • ????int?coi?=?getCurrentOrientationIndexForGlobalIcons();??
  • ????if?(sGlobalSearchIcon[coi]?==?null?||?sVoiceSearchIcon[coi]?==?null?||??
  • ????????????sAppMarketIcon[coi]?==?null)?{??
  • ????????updateAppMarketIcon();??
  • ????????searchVisible?=?updateGlobalSearchIcon();??
  • ????????voiceVisible?=?updateVoiceSearchIcon(searchVisible);??
  • ????}??
  • ????if?(sGlobalSearchIcon[coi]?!=?null)?{??
  • ?????????updateGlobalSearchIcon(sGlobalSearchIcon[coi]);??
  • ?????????searchVisible?=?true;??
  • ????}??
  • ????if?(sVoiceSearchIcon[coi]?!=?null)?{??
  • ????????updateVoiceSearchIcon(sVoiceSearchIcon[coi]);??
  • ????????voiceVisible?=?true;??
  • ????}??
  • ????if?(sAppMarketIcon[coi]?!=?null)?{??
  • ????????updateAppMarketIcon(sAppMarketIcon[coi]);??
  • ????}??
  • ????mSearchDropTargetBar.onSearchPackagesChanged(searchVisible,?voiceVisible);??
  • ??
  • ????//?On?large?interfaces,?we?want?the?screen?to?auto-rotate?based?on?the?current?orientation??
  • ????if?(LauncherApplication.isScreenLarge()?||?Build.TYPE.contentEquals("eng"))?{??
  • ????????setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);??
  • ????}??
  • }??
  • ?

    ??? Step 7:其中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?void?bindPackagesUpdated();??
  • ???????public?boolean?isAllAppsVisible();??
  • ???????public?void?bindSearchablesChanged();??
  • ???}??
  • ?

    ?

    對LauncherModel進行初始化的時候mModel = app.setLauncher(this);---->mModel.initialize(launcher);----->

    ???????????? ?public void initialize(Callbacks callbacks) {
    ????????????????????? synchronized (mLock) {
    ????????????????????????????? mCallbacks = new WeakReference<Callbacks>(callbacks);
    ????????????????????? ?}
    ?????????????? }

    這 個callbacks就是定義的接口回調,具體實現是在Launcher.java中定義的,啟動Launcher的過程中,這些實現是異步來實現的。還 有Launcher.java的onResume()方法沒有講解,到這兒基本上Android的Launcher已經啟動起來了,這個 onResume()我研究后再更新。

    ????? 歡迎各界同僚留言指正錯誤和拍磚!歡迎留言!

    轉載于:https://www.cnblogs.com/xiaochao1234/p/4054109.html

    總結

    以上是生活随笔為你收集整理的Android4.0源码Launcher启动流程分析【android源码Launcher系列一】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。