欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android開發(fā)Launcher進(jìn)程啟動(dòng)流程

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

1、Launcher

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

2、Launcher進(jìn)程啟動(dòng)流程

2.1、SystemServer調(diào)用

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

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

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啟動(dòng)的時(shí)候,執(zhí)行startOtherServices()方法中,里面調(diào)用了AMS的systemReady()方法,通過該方法來啟動(dòng)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()方法,獲取到要啟動(dòng)的HomeActivity的intent對(duì)象,其中mTopAction默認(rèn)為INTENT.ACTION_MAIN,并添加CATEGORY_HOME的category標(biāo)志;

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

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、啟動(dòng)Launcher

在startHomeActivity()方法中,調(diào)用obtainStarter()方法獲取到一個(gè)ActivityStarter對(duì)象,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();
  }
}

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

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

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

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

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

// 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)造方法中,會(huì)新建InvariantDeviceProfile對(duì)象,這個(gè)類主要是存儲(chǔ)App的基本配置信息,例如App圖標(biāo)的尺寸大小,文字大小,每個(gè)工作空間或文件夾能顯示多少App等;
在LauncherAppState的構(gòu)造方法中,會(huì)獲取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、注冊(cè)Intent廣播

新建LauncherModel對(duì)象,該對(duì)象是一個(gè)BroadcastReceiver,并添加App變化的回調(diào),以及設(shè)置Filter并注冊(cè)廣播,用于監(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()方法中,新建了一個(gè)LoaderResults對(duì)象,并通過startLoaderForResults()方法創(chuàng)建出一個(gè)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()方法中,去加載手機(jī)已安裝的App的信息,查詢數(shù)據(jù)庫(kù)獲取已安裝的App的相關(guān)信息,加載Launcher布局,并將數(shù)據(jù)轉(zhuǎn)化為View,綁定到界面上,由此我們就可以看到桌面顯示的宮格列表的桌面圖標(biāo)了;

public void run() {
  ...
  try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
    // 查詢數(shù)據(jù)庫(kù)整理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進(jìn)程啟動(dòng)流程的詳細(xì)內(nèi)容,更多關(guān)于Android Launcher啟動(dòng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android逐幀動(dòng)畫實(shí)現(xiàn)代碼

    Android逐幀動(dòng)畫實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了Android逐幀動(dòng)畫實(shí)現(xiàn)代碼,可以通過xml或java代碼實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • RxRetroHttp為多套API請(qǐng)求適配而生

    RxRetroHttp為多套API請(qǐng)求適配而生

    今天小編就為大家分享一篇關(guān)于RxRetroHttp為多套API請(qǐng)求適配而生,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Android MediaPlayer 播放音頻的方式

    Android MediaPlayer 播放音頻的方式

    這篇文章主要介紹了Android MediaPlayer 播放音頻的方式,本文給大家詳細(xì)介紹了MediaPlayer的使用方式,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Android實(shí)現(xiàn)屏幕鎖定源碼詳解

    Android實(shí)現(xiàn)屏幕鎖定源碼詳解

    本篇文章主要介紹了Android實(shí)現(xiàn)屏幕鎖定源碼詳解,屏幕鎖定是一個(gè)很有用的功能,有需要的可以了解一下。
    2016-10-10
  • Android如何監(jiān)聽屏幕旋轉(zhuǎn)

    Android如何監(jiān)聽屏幕旋轉(zhuǎn)

    這篇文章主要介紹了如何監(jiān)聽Android屏幕旋轉(zhuǎn),幫助大家更好的理解和學(xué)習(xí)使用Android開發(fā),感興趣的朋友可以了解下
    2021-03-03
  • Android入門之Handler的使用教程詳解

    Android入門之Handler的使用教程詳解

    這篇文章主要為大家詳細(xì)介紹了Android中Handler機(jī)制的使用,文中的示例代碼講解詳細(xì),有需要的朋友可以借鑒參考下,希望能夠?qū)Υ蠹矣兴鶐椭?/div> 2022-11-11
  • 藍(lán)牙原理Android代碼實(shí)現(xiàn)

    藍(lán)牙原理Android代碼實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了藍(lán)牙原理Android代碼實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android 開發(fā)線程的分析

    Android 開發(fā)線程的分析

    這篇文章主要介紹了Android 開發(fā)線程的分析的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 利用Flutter實(shí)現(xiàn)背景圖片毛玻璃效果實(shí)例

    利用Flutter實(shí)現(xiàn)背景圖片毛玻璃效果實(shí)例

    Flutter沒有單獨(dú)的模糊處理容器,需要部件層層疊加實(shí)現(xiàn)模糊效果,下面這篇文章主要給大家介紹了關(guān)于利用Flutter實(shí)現(xiàn)背景圖片毛玻璃效果的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • kotlin中的數(shù)據(jù)轉(zhuǎn)換方法(示例詳解)

    kotlin中的數(shù)據(jù)轉(zhuǎn)換方法(示例詳解)

    這篇文章介紹了Kotlin中將數(shù)字轉(zhuǎn)換為字符串和字符串轉(zhuǎn)換為數(shù)字的多種方法,包括使用`toString()`、字符串模板、格式化字符串、處理可空類型等,同時(shí),也詳細(xì)講解了如何安全地進(jìn)行字符串到數(shù)字的轉(zhuǎn)換,并處理了不同進(jìn)制和本地化格式的字符串轉(zhuǎn)換,感興趣的朋友一起看看吧
    2025-03-03

最新評(píng)論