Android11(API30)中Activity的启动流程—从startActivity到onCreate

在开发中,我们并不是使用new关键字创建Activity的,通常启动一个Activity的方式如下:

startActivity(new Intent(this, MainActivity.class));

Activity有自己的生命周期,通常意义上的生命周期第一步是onCreate。那么一个Activity是如何由startAcitivity走向onCreate的呢?

Google也在不断的对其SDK进行更新迭代。所以,不同的Android版本(谷歌分别在Android8.0、10.0、11.0三个版本都做过修改),其启动流程也有一些区别,不过整体流程上还是基本一致的。本文以当前最新的 Android11.0(API30) 为目标版本,直接从源码的走向来观察一个Activity的启动流程。。

先上一张图:

在这里插入图片描述

1,Activity#startActivityForResult

Activity中有多个启动Activity的方法,当我们调用其中一个startActivity方法时,最终都会走向下面的startActivityForResult(只保留关键代码):

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
   
    >>>
	Instrumentation.ActivityResult ar =
		mInstrumentation.execStartActivity(
			this, mMainThread.getApplicationThread(), mToken, this,
			intent, requestCode, options);
	>>>
  • Instrumentation:用于实现应用程序插装代码的基本类,主要负责ActivityApplication的创建和生命周期调用。在运行时,这个类将在任何应用程序代码之前被实例化,从而允许我们监视系统与应用程序的所有交互。系统是通过AndroidManifest.xml对系统描述插装实现的。
2,Instrumentation#execStartActivity

方法在不同得API版本中有一些区别:

Target<=API25:

public ActivityResult execStartActivity(
		Context who, IBinder contextThread, IBinder token, Activity target,
		Intent intent, int requestCode, Bundle options) {
   
	>>>
	int result = ActivityManagerNative.getDefault()
		.startActivity(whoThread, who.getBasePackageName(), intent,
				intent.resolveTypeIfNeeded(who.getContentResolver()),
				token, target != null ? target.mEmbeddedID : null,
				requestCode, 0, null, options);
	checkStartActivityResult(result, intent);//Activity是否在Manifast中注册过,就是在这个方法里校验的。
	>>>
}

在8.0之前的版本中通过ActivityManagerNative.getDefault获取ActivityManagerService的实例来调用其startActivity方法。

API26<=Target<=API28:

public ActivityResult execStartActivity(
		Context who, IBinder contextThread, IBinder token, Activity target,
		Intent intent, int requestCode, Bundle options) {
   
	>>>
	int result = ActivityManager.getService()
		.startActivity(whoThread, who.getBasePackageName(), intent,
				intent.resolveTypeIfNeeded(who.getContentResolver()),
				token, target, requestCode, 0, null, options);
	checkStartActivityResult(result, intent);//Activity是否在Manifast中注册过,就是在这个方法里校验的。
	>>>
}

在Android10之前的版本是通过ActivityManager.getService获取ActivityManagerService的实例来调用其startActivity方法。

API29<=Target:

public ActivityResult execStartActivity(
		Context who, IBinder contextThread, IBinder token, Activity target,
		Intent intent, int requestCode, Bundle options) {
   
	>>>
	int result = ActivityTaskManager.getService()
		.startActivity(whoThread, who.getBasePackageName(), intent,
				intent.resolveTypeIfNeeded(who.getContentResolver()),
				token, target != null ? target.mEmbeddedID : null,
				requestCode, 0, null, options);
	checkStartActivityResult(result, intent);//Activity是否在Manifast中注册过,就是在这个方法里校验的。
	>>>
}

从Android10开始的版本是通过ActivityTaskManager.getService获取ActivityTaskManagerService的实例来调用其startActivity方法。这篇文章我们只看Android10之后的版本。

  • ActivityTaskManager:此类提供有关activities及其容器(如任务、堆栈和Display)的信息并与之交互。

ActivityTaskManager#getService

点击getService发现直接跳转到下面这个方法:

/** @hide */
public static IActivityTaskManager getService() {
   
	return IActivityTaskManagerSingleton.get();
}

返回值是一个IActivityTaskManager 类型的对象。

  • IActivityTaskManagerIActivityTaskManager 继承了IInterface,是AMS在app进程的binder代理对象。app进程通过ActivityTaskManager.getService 返回的IActivityTaskManager来调用系统进程AMS中的方法。ActivityTaskManagerService实现了IActivityTaskManager.Stub

ActivityTaskManager#IActivityTaskManagerSingleton

@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
		new Singleton<IActivityTaskManager>() {
   
			@Override
			protected IActivityTaskManager create() {
   
				final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
				return IActivityTaskManager.Stub.asInterface(b);
			}
		};
public abstract class Singleton<T> {
   
    @UnsupportedAppUsage
    private T mInstance;

    protected abstract T create();

    @UnsupportedAppUsage
    public final T get() {
   
        synchronized (this) {
   
            if (mInstance == null) {
   
                mInstance = create();
            }
            return mInstance;
        }
    }
}
  • Singleton:是一个用于延迟初始化的单例助手类。IActivityTaskManagerSingleton.get()返回的值即为Singleton#create中返回的值。

所以,最终execStartActivity方法中调用的startActivity其实是ActivityTaskManagerService 中的startActivity方法。

  • ActivityTaskManagerService:用于管理activity及其容器(任务、堆栈、Display等)的系统服务。
3,ActivityTaskManagerService#startActivity
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
		Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
		int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
   
	return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
			resultWho, requestCode, startFlags, profilerInfo, bOptions,
			UserHandle.getCallingUserId());
}
4,ActivityTaskManagerService#startActivityAsUser
int startActivityAsUser(IApplicationThread caller, String callingPackage,
		Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
		int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
		boolean validateIncomingUser) {
   
	>>>
	// TODO: Switch to user app stacks here.
	return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
			.setCaller(caller)
			.setCallingPackage(callingPackage)
			.setResolvedType
首先,你需要在百度AI开放平台上注册账号并创建一个机器翻译应用,获取到应用的API Key和Secret Key。接着,你可以使用Android Studio创建一个新的Android项目,将获取到的API Key和Secret Key作为参数传递给百度API的SDK,实现英文互译功能。 以下是一个简单的示例代码: 1. 在app的build.gradle文件添加百度API的Maven库依赖: ``` repositories { mavenCentral() maven { url "http://maven.baidu.com/artifact/com.baidu.aip/sdk" } } ``` 2. 在AndroidManifest.xml文件添加网络访问权限: ``` <uses-permission android:name="android.permission.INTERNET" /> ``` 3. 在MainActivity.java编写英文互译的代码: ``` import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.TextView; import com.baidu.aip.translate.Translate; import com.baidu.aip.translate.TranslateErrorCode; public class MainActivity extends AppCompatActivity { private EditText editText; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = findViewById(R.id.edit_text); textView = findViewById(R.id.text_view); } public void translate(View view) { final String query = editText.getText().toString(); new Thread(new Runnable() { @Override public void run() { Translate.setClientId("your_client_id"); Translate.setClientSecret("your_secret_key"); Translate api = new Translate(); api.setRetryTime(3); api.setSleepTime(1000); TranslateResult result = api.getTransResult(query, "auto", "en"); if (result != null && result.getError_code() == TranslateErrorCode.SUCCESS) { final String dst = result.getDst(); runOnUiThread(new Runnable() { @Override public void run() { textView.setText(dst); } }); } else { Log.e("Translate", "translate error: " + result.getError_code()); } } }).start(); } } ``` 其,`setClientId()`和`setClientSecret()`方法用于设置API Key和Secret Key,`getTransResult()`方法用于调用翻译服务,第一个参数为要翻译的文本,第二个参数为源语言("auto"表示自动检测),第三个参数为目标语言。 4. 在activity_main.xml添加界面布局: ``` <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入要翻译的文本"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="翻译" android:onClick="translate"/> <TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> ``` 这样,一个简单的英文互译应用就完成了。当用户输入要翻译的文本并点击“翻译”按钮时,程序将自动调用百度API进行翻译,并将翻译结果显示在界面上。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值