最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android開發(fā)Launcher進程啟動流程

 更新時間:2023年06月20日 10:31:41   作者:安安_660c  
這篇文章主要為大家介紹了Android開發(fā)Launcher進程啟動流程示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

1、Launcher

Launcher作為Android系統(tǒng)的桌面,它的作用有兩點:
作為Android系統(tǒng)的啟動器,用于啟動應(yīng)用程序;
作為Android系統(tǒng)的桌面,用于顯示和管理應(yīng)用程序的快捷圖標(biāo)或者其它桌面組件;

2、Launcher進程啟動流程

2.1、SystemServer調(diào)用

在SystemServer進程啟動之后,執(zhí)行其run()函數(shù),在里面執(zhí)行了大量的配置設(shè)置操作,并且啟動了各種引導(dǎo)服務(wù)、核心服務(wù)以及其他服務(wù)等,包括AMS、PMS、WMS、電量管理服務(wù)等一系列服務(wù),以及創(chuàng)建主線程Looper,并循環(huán)等待消息;

其中在啟動引導(dǎo)服務(wù)方法中,啟動了ActivityManagerService,并且在啟動其他服務(wù)的方法中,調(diào)用AMS的systemReady()方法,Launcher進程就是從這兒開始啟動的;

public final class SystemServer {
    private void run() {
    ...
    startBootstrapServices();
    startOtherServices();
    ...
  }
  private void startBootstrapServices() {
    ...
    mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    ...
  }
  private void startOtherServices() {
    ...
    mActivityManagerService.systemReady(() -> { 
    }, BOOT_TIMINGS_TRACE_LOG);
  }
}

在SystemServer啟動的時候,執(zhí)行startOtherServices()方法中,里面調(diào)用了AMS的systemReady()方法,通過該方法來啟動Launcher;

// Tag for timing measurement of main thread.
private static final String SYSTEM_SERVER_TIMING_TAG = "SystemServerTiming";
private static final TimingsTraceLog BOOT_TIMINGS_TRACE_LOG
            = new TimingsTraceLog(SYSTEM_SERVER_TIMING_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
private void startOtherServices() {
  ...
  mActivityManagerService.systemReady(() -> {
    Slog.i(TAG, "Making services ready");
    traceBeginAndSlog("StartActivityManagerReadyPhase");
    mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
    ...
  }, BOOT_TIMINGS_TRACE_LOG);
}

2.2、AMS執(zhí)行

在AMS中執(zhí)行systemReady()方法,在其中執(zhí)行startHomeActivityLocked()方法,傳入當(dāng)前用戶ID;

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
  ...
  synchronized (this) {
    ...
    startHomeActivityLocked(currentUserId, "systemReady");
    ...
  }
  ...
}

2.2.1、獲取Launcher的Intent

在startHomeActivityLocked()方法中,首先通過getHomeIntent()方法,獲取到要啟動的HomeActivity的intent對象,其中mTopAction默認(rèn)為INTENT.ACTION_MAIN,并添加CATEGORY_HOME的category標(biāo)志;

得到Intent對象,通過PackageManager去獲取對應(yīng)符合的Activity,獲取對應(yīng)的ActivityInfo,并獲取對應(yīng)的進程記錄,此時對應(yīng)的進程還沒啟動,后面繼續(xù)執(zhí)行,為intent添加FLAG_ACTIVITY_NEW_TASK啟動參數(shù),開啟新棧,隨后調(diào)用ActivityStartController類的startHomeActivity()方法去執(zhí)行啟動;

boolean startHomeActivityLocked(int userId, String reason) {
  ...
  Intent intent = getHomeIntent(); 
  ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
  if (aInfo != null) {
    intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
    // Don't do this if the home app is currently being instrumented.
    aInfo = new ActivityInfo(aInfo);
    aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
    ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true);
    if (app == null || app.instr == null) {
      intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
      final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
      // For ANR debugging to verify if the user activity is the one that actually launched.
      final String myReason = reason + ":" + userId + ":" + resolvedUserId;
      mActivityStartController.startHomeActivity(intent, aInfo, myReason);
    }
  }
  ...
  return true;
}
Intent getHomeIntent() {
  Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  intent.setComponent(mTopComponent);
  intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
  if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
    intent.addCategory(Intent.CATEGORY_HOME);
  }
  return intent;
}

2.2.2、啟動Launcher

在startHomeActivity()方法中,調(diào)用obtainStarter()方法獲取到一個ActivityStarter對象,setCallingUid()方法設(shè)置當(dāng)前調(diào)用的Uid=0,然后執(zhí)行其execute()方法;

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
  mSupervisor.moveHomeStackTaskToTop(reason);
  mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
    .setOutActivity(tmpOutRecord)
    .setCallingUid(0)
    .setActivityInfo(aInfo)
    .execute();
  mLastHomeActivityStartRecord = tmpOutRecord[0];
  if (mSupervisor.inResumeTopActivity) {
    // If we are in resume section already, home activity will be initialized, but not
    // resumed (to avoid recursive resume) and will stay that way until something pokes it
    // again. We need to schedule another resume.
    mSupervisor.scheduleResumeTopActivities();
  }
}

在ActivityStarter的execute()方法中,mayWait默認(rèn)為false,執(zhí)行startActivity()方法;

int execute() {
  try {
    // TODO(b/64750076): Look into passing request directly to these methods to allow
    // for transactional diffs and preprocessing.
    if (mRequest.mayWait) {
      return startActivityMayWait(mRequest.caller, mRequest.callingUid,  ...);
    } else {
      return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, ...);
    }
  } finally {
    onExecutionComplete();
  }
}

這里進入了Activity的啟動流程,Launcher本身就是一個系統(tǒng)APP,用于顯示桌面等,LauncherApp啟動之后會執(zhí)行其生命周期方法初始化桌面布局;

2.3、初始化桌面圖標(biāo)

2.3.1、執(zhí)行onCreate()方法

@Override
protected void onCreate(Bundle savedInstanceState) {
  ...
  LauncherAppState app = LauncherAppState.getInstance(this);
  ...
}

獲取LauncherAppState,通過LauncherAppState的getInstance()方法獲取,該方法里面會判斷當(dāng)前線程是否為主線程,在主線程時還會直接new出對象,不在主線程時,通過MainThreadExecutor的submit()方法向主線程提交一個任務(wù)去獲取該對象;

// We do not need any synchronization for this variable as its only written on UI thread.
private static LauncherAppState INSTANCE;
public static LauncherAppState getInstance(final Context context) {
  if (INSTANCE == null) {
    if (Looper.myLooper() == Looper.getMainLooper()) {
      INSTANCE = new LauncherAppState(context.getApplicationContext());
    } else {
      try {
        return new MainThreadExecutor().submit(new Callable<LauncherAppState>() {
          @Override
          public LauncherAppState call() throws Exception {
            return LauncherAppState.getInstance(context);
          }
        }).get();
      } catch (InterruptedException|ExecutionException e) {
        throw new RuntimeException(e);
      }
    }
  }
  return INSTANCE;
}

2.3.2、讀取安裝APP信息

在LauncherAppState的構(gòu)造方法中,會新建InvariantDeviceProfile對象,這個類主要是存儲App的基本配置信息,例如App圖標(biāo)的尺寸大小,文字大小,每個工作空間或文件夾能顯示多少App等;
在LauncherAppState的構(gòu)造方法中,會獲取WindowManager,并獲取屏幕的尺寸,解析桌面布局文件,獲取默認(rèn)尺寸信息等;

@TargetApi(23)
public InvariantDeviceProfile(Context context) {
  WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  Display display = wm.getDefaultDisplay();
  DisplayMetrics dm = new DisplayMetrics();
  display.getMetrics(dm);
  ...
  ArrayList<InvariantDeviceProfile> closestProfiles = findClosestDeviceProfiles(minWidthDps, minHeightDps, getPredefinedDeviceProfiles(context));
  ...
}
ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles(Context context) {
  ArrayList<InvariantDeviceProfile> profiles = new ArrayList<>();
  try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
    final int depth = parser.getDepth();
    int type;
    while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
      if ((type == XmlPullParser.START_TAG) && "profile".equals(parser.getName())) {
        TypedArray a = context.obtainStyledAttributes(Xml.asAttributeSet(parser), R.styleable.InvariantDeviceProfile);
        int numRows = a.getInt(R.styleable.InvariantDeviceProfile_numRows, 0);
        int numColumns = a.getInt(R.styleable.InvariantDeviceProfile_numColumns, 0);
        float iconSize = a.getFloat(R.styleable.InvariantDeviceProfile_iconSize, 0);
        profiles.add(new InvariantDeviceProfile(
          a.getString(R.styleable.InvariantDeviceProfile_name),
          a.getFloat(R.styleable.InvariantDeviceProfile_minWidthDps, 0),
          a.getFloat(R.styleable.InvariantDeviceProfile_minHeightDps, 0),
          numRows,
          numColumns,
          a.getInt(R.styleable.InvariantDeviceProfile_numFolderRows, numRows),
          a.getInt(R.styleable.InvariantDeviceProfile_numFolderColumns, numColumns),
          iconSize,
          a.getFloat(R.styleable.InvariantDeviceProfile_landscapeIconSize, iconSize),
          a.getFloat(R.styleable.InvariantDeviceProfile_iconTextSize, 0),
          a.getInt(R.styleable.InvariantDeviceProfile_numHotseatIcons, numColumns),
          a.getResourceId(R.styleable.InvariantDeviceProfile_defaultLayoutId, 0),
          a.getResourceId(R.styleable.InvariantDeviceProfile_demoModeLayoutId, 0)));
        a.recycle();
      }
    }
  } catch (IOException|XmlPullParserException e) {
    throw new RuntimeException(e);
  }
  return profiles;
}

2.3.3、注冊Intent廣播

新建LauncherModel對象,該對象是一個BroadcastReceiver,并添加App變化的回調(diào),以及設(shè)置Filter并注冊廣播,用于監(jiān)聽桌面App的變化;

private LauncherAppState(Context context) {
  ...
  mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
  LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);
  // Register intent receivers
  IntentFilter filter = new IntentFilter();
  filter.addAction(Intent.ACTION_LOCALE_CHANGED);
  // For handling managed profiles
  filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
  filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
  ...
  mContext.registerReceiver(mModel, filter);
  ...
}
public class LauncherModel extends BroadcastReceiver ... {}

2.3.4、解析Launcher布局

繼續(xù)回到Launcher的onCreate()方法,將Launcher添加到LauncherModel中,是以弱引用的方式添加,初始化一些其工作,解析Launcher的布局,

2.3.5、加載桌面

onCreate()方法中,通過LauncherModel的startLoader()來加載桌面App;

@Override
protected void onCreate(Bundle savedInstanceState) {
  ...
  if (!mModel.startLoader(currentScreen)) {
    if (!internalStateHandled) {
      // If we are not binding synchronously, show a fade in animation when
      // the first page bind completes.
      mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
    }
  } else {
    // Pages bound synchronously.
    mWorkspace.setCurrentPage(currentScreen);
    setWorkspaceLoading(true);
  }
  ...
}

在LauncherModel的startLoader()方法中,新建了一個LoaderResults對象,并通過startLoaderForResults()方法創(chuàng)建出一個LoaderTask的Runnable任務(wù),將其在工作線程中執(zhí)行起來;

public boolean startLoader(int synchronousBindPage) {
  ...
  synchronized (mLock) {
    // Don't bother to start the thread if we know it's not going to do anything
    if (mCallbacks != null &amp;&amp; mCallbacks.get() != null) {
      ...
      LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel, mBgAllAppsList, synchronousBindPage, mCallbacks);
      if (mModelLoaded &amp;&amp; !mIsLoaderTaskRunning) {
        ...
        return true;
      } else {
        startLoaderForResults(loaderResults);
      }
    }
  }
  return false;
}
public void startLoaderForResults(LoaderResults results) {
  synchronized (mLock) {
    stopLoader();
    mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
    runOnWorkerThread(mLoaderTask);
  }
}
private static void runOnWorkerThread(Runnable r) {
  if (sWorkerThread.getThreadId() == Process.myTid()) {
    r.run();
  } else {
    // If we are not on the worker thread, then post to the worker handler
    sWorker.post(r);
  }
}

在LoaderTask的run()方法中,去加載手機已安裝的App的信息,查詢數(shù)據(jù)庫獲取已安裝的App的相關(guān)信息,加載Launcher布局,并將數(shù)據(jù)轉(zhuǎn)化為View,綁定到界面上,由此我們就可以看到桌面顯示的宮格列表的桌面圖標(biāo)了;

public void run() {
  ...
  try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
    // 查詢數(shù)據(jù)庫整理App信息,轉(zhuǎn)化為View綁定到界面
    loadWorkspace();
    mResults.bindWorkspace();
    loadAllApps();
    mResults.bindAllApps();
    loadDeepShortcuts();
    mResults.bindDeepShortcuts();
    mBgDataModel.widgetsModel.update(mApp, null);
    mResults.bindWidgets();
    transaction.commit();
  } catch (CancellationException e) {
    // Loader stopped, ignore
    TraceHelper.partitionSection(TAG, "Cancelled");
  }
  TraceHelper.endSection(TAG);
}

以上就是Android開發(fā)Launcher進程啟動流程的詳細(xì)內(nèi)容,更多關(guān)于Android Launcher啟動的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android App打包加固后的APK無法安裝問題解決

    Android App打包加固后的APK無法安裝問題解決

    Android應(yīng)用當(dāng)中,很多隱私信息都是以 字符串的形式存在的,所以需要加密,本文主要介紹了Android App打包加固后的APK無法安裝問題解決,感興趣的可以了解一下
    2024-01-01
  • 淺談Android 指紋解鎖技術(shù)

    淺談Android 指紋解鎖技術(shù)

    這篇文章主要介紹了淺談Android 指紋解鎖技術(shù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android實現(xiàn)幀動畫的兩種方式

    Android實現(xiàn)幀動畫的兩種方式

    幀動畫(Frame?Animation)是一種在一定時間內(nèi)按順序播放一系列圖像幀(每一幀都是一個單獨的圖像),從而產(chǎn)生連續(xù)運動或變化的動畫效果,本文給大家介紹了Android實現(xiàn)幀動畫的兩種方式,需要的朋友可以參考下
    2024-02-02
  • Android實現(xiàn)一個簡單帶動畫的展開收起功能

    Android實現(xiàn)一個簡單帶動畫的展開收起功能

    今天給大家?guī)硪粋€展開和收起的簡單效果,如果只是代碼中簡單設(shè)置顯示或隱藏,熟悉安卓系統(tǒng)的朋友都知道,那一定是閃現(xiàn),所以筆者結(jié)合了動畫,使得體驗效果瞬間提升一個檔次,感興趣的小伙伴可以自己動手試一試
    2023-08-08
  • android自定義ImageView仿圖片上傳示例

    android自定義ImageView仿圖片上傳示例

    本篇文章主要介紹了android自定義ImageView仿圖片上傳,具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01
  • Android中findViewById返回為空null的快速解決辦法

    Android中findViewById返回為空null的快速解決辦法

    這篇文章主要介紹了Android中findViewById返回為空null的快速解決辦法的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • Android 實現(xiàn)夜間模式的快速簡單方法實例詳解

    Android 實現(xiàn)夜間模式的快速簡單方法實例詳解

    這篇文章主要介紹了Android 實現(xiàn)夜間模式的快速簡單方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • 詳解Android Handler的使用

    詳解Android Handler的使用

    這篇文章主要介紹了Android Handler使用的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下
    2021-04-04
  • Kotlin基本類型自動裝箱一點問題剖析

    Kotlin基本類型自動裝箱一點問題剖析

    這篇文章主要剖析了Kotlin基本類型自動裝箱的一點問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 自己實現(xiàn)的android樹控件treeview

    自己實現(xiàn)的android樹控件treeview

    在項目中經(jīng)常需要一個需要一個樹狀框架,因為一些原因沒有使用系統(tǒng)自帶的控件,所以就自己寫了一個,現(xiàn)在分享給大家
    2014-01-01

最新評論

屏边| 盱眙县| 扎鲁特旗| 东辽县| 桦南县| 大关县| 尖扎县| 柘城县| 清丰县| 托克托县| 绍兴县| 富宁县| 惠来县| 凉城县| 皮山县| 平陆县| 遵义市| 北辰区| 高雄市| 绥芬河市| 泸西县| 繁峙县| 裕民县| 卓资县| 邳州市| 莒南县| 九龙城区| 丰台区| 南华县| 越西县| 论坛| 宁国市| 南皮县| 福鼎市| 长阳| 天峻县| 沅江市| 云梦县| 临江市| 冷水江市| 体育|