36

Android中Activity的startActivity和Context的startActivity有什么不同

 5 years ago
source link: https://segmentfault.com/a/1190000018423363?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

原文: http://tryenough.com/android-...

在使用中的不同

1.在Activity中跳转到其他的Activity时,两种使用方法是一样的:

this.startActivity(intent);
context.startActivity(intent);

2.从非 Activity (例如从其他Context中)启动Activity则必须给intent设置 Flag:FLAG_ACTIVITY_NEW_TASK :

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ; 
mContext.startActivity(intent);

探究一下为什么会有这方面的差异

原文: http://tryenough.com/android-...

首先看下Activity和context的继承关系:

RrMvamz.png!web

要知道Activity和context中的StartActivity有什么区别,我们看下它们分别是怎么实现startActivity函数的:

原文: http://tryenough.com/android-...

1.Context是抽象类,它的startActivity函数是抽象方法:

public abstract void startActivity(@RequiresPermission Intent intent);

2.ContextWrapper类只是调用了Context的实现:

@Override
public void startActivity(Intent intent) {
    mBase.startActivity(intent);
}

3.ContextThemeWrapper中没有实现此方法

4.Activity中:

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

由此可见,在Activity中无论是使用哪一种startActivity方法都会调用到Activity自身的方法,所以是一样的。

原文: http://tryenough.com/android-...

然而在其他的Context子类,例如ContextImpl.java中的实现,会检查有没有设置Flag:FLAG_ACTIVITY_NEW_TASK,否则会报错:

@Override
    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);
    }

原文: http://tryenough.com/android-...

这也就是为什么Activity的startActivity和Context的startActivity会有上面那些使用上的不同的原因了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK