Activity的起步流程分析
Activity的起步流程分析
為了在手機畫面上顯示Activity的window,android內部會做一下內容:
1) 建立一個Window在Window裡構建View Hierachy。
2) 與WindowManager建立聯絡。
3) 為了與SystemServer通訊,開啟Binder裝置。
4) 把Window註冊上去,確定View Hierachy大小,位置。
5) 確定大小,位置後在Surface中開始Draw。
6) 把Surface輸出在LCD中。
就這樣我們就能從手機螢幕中看到了。
Activity的啟動簡單來說就兩種:
- 點選應用程式圖示啟動Activity( luncher啟動 )。
- 從一個Activity跳轉到另一個Activity ( 也就是說從一個Activity中執行startActivity() )。
首先我們看一下Manifast.xml檔案(為了體現兩種啟動方式而自定義的Manifast)
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.com.activitytest" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- MainActivity是點選應用程式圖示來啟動Activity--> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- SubActivity是MainActivity呼叫startActivity函式來啟動Activity--> <activity android:name=".SubActivity" android:label="@string/sub_activity"> </activity> </application> </manifest>
1. MainActivity的啟動
首先我們先分析MainActivity的啟動
分析之前我們先看一下Manifast中的 <category android:name="android.intent.category.LAUNCHER" /> ,表示要用LAUNCHER啟動。
- Launcher:Launcher本身也是一個應用程式,其它的應用程式安裝後,就會Launcher的介面上出現一個相應的應用程式圖示。
當我們點選相應的應用程式圖示時,Launcher就會啟動對應的應用程。
下面是Launcher的原始碼
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { ...... /** * Launches the intent referred by the clicked shortcut. * * @param v The view representing the clicked shortcut. */ public void onClick(View v) { Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { // Open shortcut final Intent intent = ((ShortcutInfo) tag).intent; int[] pos = new int[2]; v.getLocationOnScreen(pos); intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight())); startActivitySafely(intent, tag); } else if (tag instanceof FolderInfo) { ...... } else if (v == mHandleView) { ...... } } void startActivitySafely(Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { startActivity(intent); } catch (ActivityNotFoundException e) { ...... } catch (SecurityException e) { ...... } } ...... }
從程式碼中可知,當我們點選某個應用程式圖示時會觸發Launcher的public
void onClick(View v)點選事件。
然後呼叫ShortcutInfo中的startActivitySafely(intent, tag);- > startActivity(intent);。
- Intent.FLAG_ACTIVITY_NEW_TASK:表示要在一個新的Task中啟動這個Activity。
startActivity函式是啟動的Activity的startActivity函式。
frameworks/base/core/java/android/app/Activity.java
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks { ...... @Override public void startActivity(Intent intent) { startActivityForResult(intent, -1); } ...... }
還會呼叫startActivityForResult來進一步處理,第二個引數傳入-1表示不需要這個Actvity結束後的返回結果。
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks { ...... public void startActivityForResult(Intent intent, int requestCode) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode); ...... } else { ...... } ...... }
frameworks/base/core/java/android/app/Instrumentation.java
public class Instrumentation { ...... public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { ...... } try { int result = ActivityManagerNative.getDefault() .startActivity(whoThread, intent, intent.resolveTypeIfNeeded(who.getContentResolver()), null, 0, token, target != null ? target.mEmbeddedID : null, requestCode, false, false); ...... } catch (RemoteException e) { } return null; } ...... }
重要角色出來了ActivityManagerNative.getDefault()返回ActivityManagerService。
ActivityManagerService是在另外一個程式中所以需要呼叫它的代理服務。即ActivityManagerProxy。
frameworks/base/core/java/android/app/ActivityManagerNative.java(內部類)
class ActivityManagerProxy implements IActivityManager { ...... public int startActivity(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeTypedArray(grantedUriPermissions, 0); data.writeInt(grantedMode); data.writeStrongBinder(resultTo); data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(onlyIfNeeded ? 1 : 0); data.writeInt(debug ? 1 : 0); mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); int result = reply.readInt(); reply.recycle(); data.recycle(); return result; } ...... }
最終還會呼叫ActivityManagerService(frameworks/base/services/java/com/android/server/am/ActivityManagerService.java)的startActivity函式
而在此函式中沒有其他動作,僅僅做了一個轉發,呼叫了ActivityStack.startActivityMayWait函式
frameworks/base/services/java/com/android/server/am/ActivityStack.java
public class ActivityStack { ...... final int startActivityMayWait(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug, WaitResult outResult, Configuration config) { ...... boolean componentSpecified = intent.getComponent() != null; intent = new Intent(intent); // 解析AndroidManifest.xml,得知activity的報名及activity的類名。 ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { ...... } if (aInfo != null) { // 指定具體的元件類,通知應用啟動對應的元件。 intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); ...... } synchronized (mService) { int callingPid; int callingUid; if (caller == null) { ...... } else { callingPid = callingUid = -1; } mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; ...... if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { ...... } int res = startActivityLocked(caller, intent, resolvedType, grantedUriPermissions, grantedMode, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, onlyIfNeeded, componentSpecified); if (mConfigWillChange && mMainStack) { ...... } ...... if (outResult != null) { ...... } return res; } } ...... }
最後呼叫startActivityLocked
frameworks/base/services/java/com/android/server/am/ActivityStack.java
public class ActivityStack { ...... final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, ActivityInfo aInfo, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, boolean onlyIfNeeded, boolean componentSpecified) { int err = START_SUCCESS; ProcessRecord callerApp = null; if (caller != null) { callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { ...... } } ...... ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { int index = indexOfTokenLocked(resultTo); ...... if (index >= 0) { sourceRecord = (ActivityRecord)mHistory.get(index); if (requestCode >= 0 && !sourceRecord.finishing) { ...... } } } int launchFlags = intent.getFlags(); if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { ...... } ...... ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified); ...... return startActivityUncheckedLocked(r, sourceRecord, grantedUriPermissions, grantedMode, onlyIfNeeded, true); } ...... }
從caller(ApplicationThread)中獲取程式(launcher程式)資訊儲存在ProcessRecord callerApp=mService.getRecordForAppLocked(caller);
建立即將要啟動的Activity的相關資訊ActivityRecord r = new ActivityRecord函式。
而在startActivityUncheckedLocked函式中把Task儲存在r.task域中,同時,新增到mService中去,這裡的mService就是ActivityManagerService了。呼叫startActivityLocked(r, newTask, doResume)
frameworks/base/services/java/com/android/server/am/ActivityStack.java
public class ActivityStack { ...... private final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume) { final int NH = mHistory.size(); int addPos = -1; if (!newTask) { ...... } // Place a new activity at top of stack, so it is next to interact // with the user. if (addPos < 0) { addPos = NH; } // If we are not placing the new activity frontmost, we do not want // to deliver the onUserLeaving callback to the actual frontmost // activity if (addPos < NH) { ...... } // Slot the activity into the history stack and proceed mHistory.add(addPos, r); r.inHistory = true; r.frontOfTask = newTask; r.task.numActivities++; //NH表示當前系統中歷史任務的個數 if (NH > 0) { // We want to show the starting preview window if we are // switching to a new task, or the next activity's process is // not currently running. ...... } else { // If this is the first activity, don't do any fancy animations, // because there is nothing for it to animate on top of. ...... } ...... if (doResume) { resumeTopActivityLocked(null); } } ...... }
resumeTopActivityLocked(null); 函式獲得堆疊頂端的Activity,即MainActivity。
MainActivity建立了ActivityRecord後,它的app域一直保持為null。有了這些資訊後,上面這段程式碼就容易理解了,它最終呼叫startSpecificActivityLocked進行下一步操作。
rameworks/base/services/java/com/android/server/am/ActivityStack.java
public class ActivityStack { ...... private final void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // 由於是第一次啟動應用程式的Activity,所以下面語句 ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid); ...... if (app != null && app.thread != null) { try { realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { ...... } } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false); } ...... }
mService.getProcessRecordLocked此函式是在AMS中,路徑如下
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
在此函式中建立一個ProcessRecord,呼叫startProcessLocked。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
在startProcessLocked函式中:
int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null, uid, uid, gids, debugFlags, null);
在這我們可以看到他會啟動一個Process,而這個Process由Zygote建立的。在前幾節中我們講過有關Zygote,在那裡我們提過Zygote的客戶端也可以是AMS。從這裡我們可以看出這一點。
接下來通過ActivityThread會呼叫Activity的onCread()。
2. SubActivity的啟動
其實利用MainActivity中的元件(如:button.onclick)去startActivity是與Launcher中啟動時一樣的,從上面分析的內容中可以看出Luancher最終也會呼叫startActivity。
僅僅是呼叫subActivity時不會建立一個Process,僅僅利用當場執行緒去建立而已。然後退回到Main函式時時從ActivityStack中Pause的Activity重新顯現出來。
可以參考下面的圖:
相關文章
- Activity啟動流程分析
- activity 啟動流程分析
- Activity啟動流程原始碼分析原始碼
- Android Activity啟動流程原始碼分析Android原始碼
- Android原始碼分析:Activity啟動流程Android原始碼
- Flutter Android 端 Activity/Fragment 流程原始碼分析FlutterAndroidFragment原始碼
- Activity啟動流程分析記錄(Api26)API
- Activity 流程模型匯入匯出-activity流程模型匯入匯出模型
- 從Activity的啟動流程理解Binder
- Application,Activity,Service的建立流程(1)APP
- Application,Activity,Service的建立流程(2)APP
- 【Android原始碼】Activity的啟動流程Android原始碼
- App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析APPAndroid
- Activity原始碼分析原始碼
- Activity 的 "啟動流程"(基於 Android 9.0)Android
- 庖丁解牛 Activity 啟動流程
- Activity 啟動流程學習總結(附原始碼流程圖)原始碼流程圖
- Activity啟動過程分析
- Activity、View、Window之間關係的分析View
- 基於8.0原始碼解析:Activity啟動流程原始碼
- 圖解Activity啟動流程,進階高階圖解
- 探索startActivity流程及在Activity間是如何傳遞Intent的Intent
- app啟動流程,activity啟動流程時序圖,binder相關資料APP時序圖
- 深入理解Activity啟動流程和AMS框架(一)框架
- 深入理解Activity啟動流程和AMS框架(二)框架
- 深入理解Activity啟動流程和AMS框架(三)框架
- webpack 起步Web
- thinkphp起步PHP
- Redis 起步Redis
- vue.js的起步Vue.js
- Activity啟動分析(一)--ActivityThreadthread
- printk 流程分析
- printk流程分析
- 探究 Android View 繪製流程,Activity 的 View 如何展示到螢幕AndroidView
- Appfuse:起步APP
- Activity啟動分析(二)--建立Window和ViewView
- 深入理解Android 之 Activity啟動流程(Android 10)Android
- Flutter setState流程分析Flutter