Android13 Context startActivity流程分析

Activity的startActivity和Context的startActivity都可以启动一个Activity,它们的区别如下:

Activity的startActivity方法:

这种方式是在Activity内部调用startActivity方法,使用的上下文对象是当前的Activity对象。这种方式会自动将当前Activity作为启动Activity的上下文,并且会将新启动的Activity添加到当前Activity所在的任务栈中。

Context的startActivity方法:

context.startActivity(intent);

这种方式是在任何地方调用startActivity方法,使用的上下文对象是一个Context对象。这种方式可以在任何地方启动Activity,不仅限于Activity内部。但是需要注意的是,如果上下文对象不是一个Activity对象,即非Activity环境启动Activity时,需要加上Intent.FLAG_ACTIVITY_NEW_TASK标志位,以创建一个新的任务栈。

Activity的startActivity方法是在Activity内部调用,使用当前Activity作为上下文对象,会将新启动的Activity添加到当前Activity所在的任务栈中。

Context的startActivity方法可以在任何地方调用,使用任意一个Context对象作为上下文对象,需要注意非Activity环境启动Activity时需要加上Intent.FLAG_ACTIVITY_NEW_TASK标志位。

Context的startActivity代码如下:

//frameworks/base/core/java/android/content/Context.java
public abstract class Context {
    public abstract void startActivity(@RequiresPermission Intent intent);
}

Context是抽象类,由其子类ContextImpl实现:

//frameworks/base/core/java/android/content/ContextImpl.java
class ContextImpl extends Context {
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }
}

调用重载方法:

//frameworks/base/core/java/android/content/ContextImpl.java
class ContextImpl extends Context {
    final @NonNull ActivityThread mMainThread;
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();


        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
        // maintain this for backwards compatibility.
        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;


        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && (targetSdkVersion < Build.VERSION_CODES.N
                        || targetSdkVersion >= Build.VERSION_CODES.P)
                && (options == null
                        || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                            + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                            + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
}

上述方法主要处理如下:

1、调用mMainThread(ActivityThread)的getInstrumentation方法,取得Instrumentation。

2、调用ContextImpl的getOuterContext方法,取得外部Context。

3、调用mMainThread(ActivityThread)的getApplicationThread方法,取得ApplicationThread。

4、调用Instrumentation的execStartActivity方法,执行应用程序发出的 startActivity 调用。

下面分别进行分析:

ActivityThread getInstrumentation

调用mMainThread(ActivityThread)的getInstrumentation方法,取得Instrumentation:

//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal {
    Instrumentation mInstrumentation;
    public Instrumentation getInstrumentation()
    {
        return mInstrumentation; //返回mInstrumentationf
    }
}

ContextImpl getOuterContext

调用ContextImpl的getOuterContext方法,取得外部Context:

//frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
    private Context mOuterContext;
    final Context getOuterContext() {
        return mOuterContext; //返回mOuterContext,mOuterContext在ContextImpl构造方法中赋值
    }
}

ActivityThread getApplicationThread

调用mMainThread(ActivityThread)的getApplicationThread方法,取得ApplicationThread:

//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal {
    final ApplicationThread mAppThread = new ApplicationThread();
    public ApplicationThread getApplicationThread()
    {
        return mAppThread;
    }
}

Instrumentation execStartActivity

调用Instrumentation的execStartActivity方法,执行应用程序发出的startActivity调用:

//frameworks/base/core/java/android/app/Instrumentation.java
public class Instrumentation {
    private List<ActivityMonitor> mActivityMonitors; //有关正在监控的特定类型的 Intent 的信息。
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle(); //Activity之间实现过渡动画效果
                        }
                        result = am.onStartActivity(who, intent, options); //调用ActivityMonitor的onStartActivity方法
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                    target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
}

调用ActivityTaskManager的getService方法,获取IActivityTaskManager接口:

//frameworks/base/core/java/android/app/Instrumentation.java
public class Instrumentation {
    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }
}

然后调用IActivityTaskManager接口的startActivity方法,IActivityTaskManager接口由ActivityTaskManagerService实现。

要注意ActivityTaskManagerService不在am目录下而在wm目录下,原因是因为它是在Android 10中引入的新功能,用于管理activities和activity相关容器(task,stacks,display)。为了更好地组织代码和功能,Android团队将ActivityTaskManagerService放置在server/wm目录下,而不是放在server/am目录下。这样可以更清晰地区分和管理不同的服务和功能模块。通过将ActivityTaskManagerService与ActivityManagerService关联起来,可以更好地实现对activity的管理和控制。

ActivityTaskManagerService startActivity

Android13 ActivityTaskManagerService startActivity流程分析-CSDN博客

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio利用Button进行跳转的流程可以分为以下几个步骤: 1. 在XML布局文件中添加Button控件并设置其属性,如id、text、color等。 2. 在Activity中获取Button控件并设置其点击事件,可以使用setOnClickListener()方法。 3. 在点击事件中使用Intent对象来实现Activity之间的跳转,可以使用startActivity()方法。 4. 在Intent对象中设置要跳转的Activity的类名,可以使用new Intent(Context packageContext, Class<?> cls)构造方法。 以下是一个简单的示例代码: 在XML布局文件中添加Button控件: ```xml <Button android:id="@+id/button" android:text="跳转到另一个Activity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" /> ``` 在Activity中获取Button控件并设置其点击事件: ```java Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, SecondActivity.class); startActivity(intent); } }); ``` 其中,MainActivity和SecondActivity分别代表当前Activity和要跳转的Activity的类名。 需要注意的是,在AndroidManifest.xml文件中需要注册要跳转的Activity,否则会出现ActivityNotFoundException异常。可以在<application>标签内添加以下代码: ```xml <activity android:name=".SecondActivity"></activity> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值