启动Activity时的方法调用(应用层)(MVC模式)

一,从桌面启动应用

从桌面启动一个应用其实质也是从一个Activity中启动另一个Activity,比如官方的实例代码中:

android/platform_packages_apps_launcher

    /**
     * 点击桌面图标启动Intent指向的Activity
     *
     * @param v The view representing the clicked shortcut.
     */
    public void onClick(View v) {
        Object tag = v.getTag();//获取点击位置
        if (tag instanceof ApplicationInfo) {//是ApplicationInfo的一个成员
            // Open shortcut
            final Intent intent = ((ApplicationInfo) tag).intent;
            startActivitySafely(intent);//启动应用
        } else if (tag instanceof FolderInfo) {
            handleFolderClick((FolderInfo) tag);
        }
    }

    void startActivitySafely(Intent intent) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
        } catch (SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            e(LOG_TAG, "Launcher does not have the permission to launch " + intent +
                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
                    "or use the exported attribute for this activity.", e);
        }
    }

二,Activity内启动Activity

因为现在几乎都是从AppCompatActivity创建Activity,所以我们从AppCompatActivity开始分析。AppCompatActivity的类继承关系如下:

我们知道,如果从自己的Activity中调用startActivity()方法,系统会在类族中从下到上依次查找,直到遇到一个startActivity()为止,所以为了方便观察,先找出各类中启动startActivity方法和startActivityForResult方法(如果类中有的话):

AppCompatActivity中没有,它会向上查找父类FragmentActivity。

FragmentActivity中有一个startActivityForResult(Intent intent, int requestCode),并且在此方法中又super了此方法,所以它会在执行完后继续向上查找startActivityForResult(intent, requestCode)方法并执行:

    /**
     * Modifies the standard behavior to allow results to be delivered to fragments.
     * This imposes a restriction that requestCode be <= 0xffff.
     */
    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
        // If this was started from a Fragment we‘ve already checked the upper 16 bits were not in
        // use, and then repurposed them for the Fragment‘s index.
        if (!mStartedActivityFromFragment) {
            if (requestCode != -1) {
                checkForValidRequestCode(requestCode);
            }
        }
        super.startActivityForResult(intent, requestCode);
    }

FragmentActivity的直接父类是BaseFragmentActivityJB,在它的类中有一个startActivityForResult(Intent intent, int requestCode,

@Nullable Bundle options)方法,显然不是FragmentActivity中那个方法调用的,FragmentActivity会再继续向上查找startActivityForResult(intent, requestCode),BaseFragmentActivityJB中的这个方法同样也super了startActivityForResult(intent, requestCode, options):

    @Override
    public void startActivityForResult(Intent intent, int requestCode,
            @Nullable Bundle options) {
        // If this was started from a Fragment we‘ve already checked the upper 16 bits were not in
        // use, and then repurposed them for the Fragment‘s index.
        if (!mStartedActivityFromFragment) {
            if (requestCode != -1) {
                checkForValidRequestCode(requestCode);
            }
        }
        super.startActivityForResult(intent, requestCode, options);
    }

然后中间几个类就没有启动Activity的方法了,看Activity:

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    @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);
        }
    }
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

因为View一般是填充到Activity中去的,如果在View类中封装的事件中需要启动Activity,会需要传入Context,这个Context一般都是所在Activity赋予,所以这种情况下也是Activity中启动Activity,所以下面判断了是不是从UI中启动:

= 0) {
                // 如果这个开始请求一个结果, 我们可以禁止让这个activity 可见,直到收到返回结果。
                // 设置这个代码使activity在 onCreate(Bundle savedInstanceState) 或者onResume() 期间处于隐藏状态,避免闪烁.
                // 只有在要求返回结果时才这么做,这样保证我们可以获得返回的信息,当activity结束,不管会发生什么。
                mStartedActivity = true;//表示启动Activity
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }" data-snippet-id="ext.a9d7a19df7f924b50221d53a62c464c0" data-snippet-saved="false" data-codota-status="done">     public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {

        if (mParent == null) {//不是从UI中启动Activity
            //实现应用检测代码的基类,内部类.ActivityResult表示返回的Activity执行的结果
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(//执行启动Activity
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(//主线程发送执行结果
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // 如果这个开始请求一个结果, 我们可以禁止让这个activity 可见,直到收到返回结果。
                // 设置这个代码使activity在 onCreate(Bundle savedInstanceState) 或者onResume() 期间处于隐藏状态,避免闪烁.
                // 只有在要求返回结果时才这么做,这样保证我们可以获得返回的信息,当activity结束,不管会发生什么。
                mStartedActivity = true;//表示启动Activity
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在上面这个startActivityForResult中会判断是不是从界面中启动,不是则执行Instrumentation.execStartActivity,如果是则执行startActivityFromChild,Activity是UI:

public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode) {
        startActivityFromChild(child, intent, requestCode, null);
    }
public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode, @Nullable Bundle options) {
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, child.mEmbeddedID, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        cancelInputsAndStartExitTransition(options);
    }

startActivityFromChild中也是执行Instrumentation.execStartActivity,其有三个同名方法,一个执行的是来自Fragment,一个来自application的,还有一个是指定用户才可以调用的,这儿为第二个:

= 0 ? am.getResult() : null;//如果有请求结果返回结果,如果没有返回null
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()//与ActivityManagerService通信启动Activity
                .startActivity(whoThread, who.getBasePackageName(), 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;
    }" data-snippet-id="ext.ee42fb8e2dd7a56f5212de6b90a201d7" data-snippet-saved="false" data-codota-status="done">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) {//如果Activity监视器不为空
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {//如果是阻塞的,暂停状态的
                            return requestCode >= 0 ? am.getResult() : null;//如果有请求结果返回结果,如果没有返回null
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()//与ActivityManagerService通信启动Activity
                .startActivity(whoThread, who.getBasePackageName(), 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;
    }

通过上面的方法可以得出,如果从我们继承自AppCompatActivit的Activity启动另一个Activity,程序执行的步骤:

结合代码可以看到从AppCompatActivity调用的startActivityForResult只是比从Activity中调用的多了以下这段代码:

//如果不是从Fragmengt启动的Activity
if (!mStartedActivityFromFragment) {
            if (requestCode != -1) {//如果请求码不是-1
                checkForValidRequestCode(requestCode);//检查给定的请求码是否有效
            }
        }

来自BaseFragmentActivityEclair:

static void checkForValidRequestCode(int requestCode) {
        if ((requestCode & 0xffff0000) != 0) {
            throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");//请求码不能超过16位
        }
    }

三,Fragment中启动Activity

在Fragment中有启动Activity的方法,可以通过它启动Activity,但在android.app包和android.support.v4.app包两个包中都Fragment类,这时就得分情况了,使用哪个包中的就导入哪个包中的Fragment。

导入android.app.Fragment

调用android.app.Fragment中的startActivity或startActivityForResult:

    /**
     * Call {@link Activity#startActivity(Intent)} from the fragment‘s
     * containing Activity.
     */
    public void startActivity(Intent intent) {
        startActivity(intent, null);
    }

    /**
     * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment‘s
     * containing Activity.
     */
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (mHost == null) {
            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
        }
        mHost.onStartActivityFromFragment(this /*fragment*/, intent, -1, options);
    }
/**
     * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment‘s
     * containing Activity.
     */
    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

    /**
     * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment‘s
     * containing Activity.
     */
    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mHost == null) {
            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
        }
        mHost.onStartActivityFromFragment(this /*fragment*/, intent, requestCode, options);
    }

可以看出startActivity和startActivityForResult调用的都是FragmentHostCallback.onStartActivityFromFragment,FragmentHostCallback是抽象类,Activity类中的内部类HostCallbacks是它的实现类:

 {
...
     @Override
        public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
                Bundle options) {
            Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
        }
...
}" data-snippet-id="ext.d72e976275f0d9a6905900a82067f2b7" data-snippet-saved="false" data-codota-status="done">class HostCallbacks extends FragmentHostCallback<Activity> {
...
     @Override
        public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
                Bundle options) {
            Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
        }
...
}

Activity.startActivityFromFragment:

    public void startActivityFromFragment(@NonNull Fragment fragment,
            @RequiresPermission Intent intent, int requestCode) {
        startActivityFromFragment(fragment, intent, requestCode, null);
    }

    public void startActivityFromFragment(@NonNull Fragment fragment,
            @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
        startActivityForResult(fragment.mWho, intent, requestCode, options);
    }

它又调用Activity类的隐藏方法startActivityForResult:

    /**
     * @hide
     */
    @Override
    public void startActivityForResult(
            String who, Intent intent, int requestCode, @Nullable Bundle options) {
        Uri referrer = onProvideReferrer();
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, who,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, who, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        cancelInputsAndStartExitTransition(options);
    }

然后最终调用Instrumentation.execStartActivity,Fragment使用的这个方法和Activity使用的同名方法的第4个参数不同,虽然含义相同:

= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
" data-snippet-id="ext.edb0134e85d5eaf562daf3ef534f5d2c" data-snippet-saved="false" data-codota-status="done">public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

流程可以简洁表示如下:

相关类图:

这儿使用了MVC架构,

;FragmentHostCallback类组为模型模块;Activity作为视图模块。

MVC架构模式

方便理解,特意百度图片:

模型(Model) “数据模型”(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。(比较:观察者模式(软件设计模式))

这儿是把Fragment当作数据,FragmentHostCallback类组对Fragment进行业务处理的封装,其子类HostCallbacks是Activity的内部类,并对Activity中的一些方法进行调用(放在Activity中方便外部调用):

 {
    public HostCallbacks() {
        super(Activity.this /*activity*/);
    }

    @Override
    public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        Activity.this.dump(prefix, fd, writer, args);
    }
    FragmentHostCallback(Activity activity) {
        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
    }

    @Override
    public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
         Bundle options) {
         Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
    }
...
}" data-snippet-id="ext.9bdfa9f42f4aef243c839ce81075651d" data-snippet-saved="false" data-codota-status="done">class HostCallbacks extends FragmentHostCallback<Activity> {
    public HostCallbacks() {
        super(Activity.this /*activity*/);
    }

    @Override
    public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        Activity.this.dump(prefix, fd, writer, args);
    }
    FragmentHostCallback(Activity activity) {
        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
    }

    @Override
    public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
         Bundle options) {
         Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
    }
...
}

视图(View) 视图层能够实现数据有目的的显示(理论上,这不是必需的)。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在它监视的数据模型那里注册。

Activity类此时在这儿充当视图层,如上在HostCallbacks的构造器中设置了模型关联的activity及上下文环境activity。Activity对控制器FragmentController进行引用,并进行一些方法调用:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
...
mFragments.dispatchResume();
mFragments.execPendingActions();

控制器(Controller) 控制器起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。

FragmentController和FragmentManager共同组成了控制器模块,FragmentController通过FragmentHostCallback.getFragmentManagerImpl()获得FragmentManager,然后共同对FragmentHostCallback进行控制,间接对Activity发挥作用:

 * It is the responsibility of the host to take care of the Fragment‘s lifecycle.
 * The methods provided by {@link FragmentController} are for that purpose.
 */
public class FragmentController {
    private final FragmentHostCallback mHost;

    /**
     * Returns a {@link FragmentController}.
     */
    public static final FragmentController createController(FragmentHostCallback callbacks) {
        return new FragmentController(callbacks);
    }

    private FragmentController(FragmentHostCallback callbacks) {
        mHost = callbacks;
    }" data-snippet-id="ext.8620cb7336dd7dc4898519dba850fdc0" data-snippet-saved="false" data-codota-status="done">/**意思是与FragmentManager一块为fragment宿主提供一个关键点,响应宿主管理fragment的生命周期。
 * Provides integration points with a {@link FragmentManager} for a fragment host.
 * <p>
 * It is the responsibility of the host to take care of the Fragment‘s lifecycle.
 * The methods provided by {@link FragmentController} are for that purpose.
 */
public class FragmentController {
    private final FragmentHostCallback<?> mHost;

    /**
     * Returns a {@link FragmentController}.
     */
    public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
        return new FragmentController(callbacks);
    }

    private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
    }

MVC模式根据情景不同,可能会有好几个嵌套,一个类会充当好几个角色。现在应用中比较流行切某些场合下更好的是MVP模式,所以了解即可。

导入android.support.v4.app.Fragment

使用android.support.v4.app.Fragment会和使用android.app.Fragment之间有稍微的差异。

android.support.v4.app.Fragment启动Activity的方法和android.app.Fragment中的代码相同,这里略。

调用的都是FragmentHostCallback.onStartActivityFromFragment,这儿的FragmentHostCallback也是抽象类,但和那个不是一个类,虽然类名相同,但所在不是同一个包(这部分的Fragment相关类在android.support.v4.app包中),它的实现类是FragmentActivity类中的内部类HostCallbacks:

        @Override
        public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
            FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode);
        }

        @Override
        public void onStartActivityFromFragment(
                Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options) {
            FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode, options);
        }

都是调用FragmentActivity.startActivityFromFragment(参数不同):

    /**
     * Called by Fragment.startActivityForResult() to implement its behavior.
     */
    public void startActivityFromFragment(Fragment fragment, Intent intent,
            int requestCode) {
        startActivityFromFragment(fragment, intent, requestCode, null);
    }

    /**
     * Called by Fragment.startActivityForResult() to implement its behavior.
     */
    public void startActivityFromFragment(Fragment fragment, Intent intent,
            int requestCode, @Nullable Bundle options) {
        mStartedActivityFromFragment = true;
        try {
            if (requestCode == -1) {
                ActivityCompat.startActivityForResult(this, intent, -1, options);
                return;
            }
            checkForValidRequestCode(requestCode);
            int requestIndex = allocateRequestIndex(fragment);
            ActivityCompat.startActivityForResult(
                    this, intent, ((requestIndex + 1) << 16) + (requestCode & 0xffff), options);
        } finally {
            mStartedActivityFromFragment = false;
        }
    }

ActivityCompat.startActivityForResult:

= 16) {
            ActivityCompatJB.startActivityForResult(activity, intent, requestCode, options);
        } else {
            activity.startActivityForResult(intent, requestCode);
        }
    }" data-snippet-id="ext.96753fe3f47654ff9d0590cacf90578e" data-snippet-saved="false" data-codota-status="done">    public static void startActivityForResult(Activity activity, Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (Build.VERSION.SDK_INT >= 16) {
            ActivityCompatJB.startActivityForResult(activity, intent, requestCode, options);
        } else {
            activity.startActivityForResult(intent, requestCode);
        }
    }

如果版本大于等于16,调用ActivityCompatJB.startActivityForResult,否则调用宿主activity的startActivityForResult(intent, requestCode),ActivityCompatJB.startActivityForResult:

public static void startActivityForResult(Activity activity, Intent intent, int requestCode, Bundle options) {
        activity.startActivityForResult(intent, requestCode, options);
    }

宿主activity即是FragmentActivity或其子类,调用的是FragmentActivity.startActivityForResult。

 @Override
    public void startActivityForResult(Intent intent, int requestCode) {
        // If this was started from a Fragment we‘ve already checked the upper 16 bits were not in
        // use, and then repurposed them for the Fragment‘s index.
        if (!mStartedActivityFromFragment) {
            if (requestCode != -1) {
                checkForValidRequestCode(requestCode);
            }
        }
        super.startActivityForResult(intent, requestCode);
    }    

后面略,请参考前面Activity中启动Activity.相关类关系和前面Fragment类关系相似,也不重复了。

附:app包中的fragment和v4包中的fragment的相关使用

1,app包中的fragment,因为这个是在3.0之后才有的,支持3.0以后的版本,如果需要支持更低版本,需要使用v4包中的fragment。’这两个类功能几乎一样,都是可以使用标签,区别是导入包时的包名是不一样的。对应的方法名类似,不尽相同,实现过程也有点差异,所以如果用混了会报错。

2,因为现在大部分都是基于AppCompatActivity使用Fragment,所以在Fragment中启动Activity如果要求返回结果,如果导入的是app包中的fragment,则有两种实现方案:

第一种:调用Fragment的startActivityForResult方法,然后在Fragment的onActivityResult的方法中处理返回的请求。

第二种:在Fragment中通过getActivity()方法获取到Fragment所在的FragmentActivity对象,调用activity对象的startActivityForResult方法启动Activity,然后在FragmentActivity的onActivityResult的方法中处理返回的请求。

四,其它组件中启动Activity

其他组件还可以启动Activity的有Service和Broadcast Receiver,他们都是脱Activity运行的。

在Service中可以直接调用startActivity(因为Service是Context的一个子类),Broadcast Receiver调用Context.startActivity,此时它们调用的方法实现都是ContextImpl.startActivity:

    @Override
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            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);
    }

可以看到这儿有个判断intent中是否有个Intent.FLAG_ACTIVITY_NEW_TASK标志,如果没有就报错。在service中启动示例:

    Intent intent=new Intent(getApplicationContext(),AnotherActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);

Broadcast Receiver同理。

五,最后附上一张图

注:这里都是用Intent传递信息,还可以使用PendingIntent。

时间: 2024-10-07 01:52:48

启动Activity时的方法调用(应用层)(MVC模式)的相关文章

解决在Fragment中启动Activity时传递请求码的问题

解决在Fragment中启动Activity时传递请求码的问题: 首先需要指出的是Fragment有startActivityForResult方法,而Activity中也有startActivityForResult方法:两者的区别是: Fragment中的startActivityForResult方法: FragmentActivity中的startActivityForResult方法: 从官方的解释中可以看出Fragment中的startActivityForResult方法是调用的是

启动activity与使用Intent通信机制解析

我们都知道,一个activity启动另一个activity最简单的方式就是使用startActivity方法: public void startActivity (Intent intent) 但是此处 应避免一个误解,该方法并不是一个类方法,启动activity时并非是针对Activity子类调用该方法, 实际上,我们是将调用请求发给了操作系统的ActivityManager,ActivityManager负责创建Activity实 例并调用onCreate(...)方法. 下面就涉及到Ac

Android 7.0 ActivityManagerService(2) 启动Activity的过程:一

从这一篇博客开始,我们将阅读AMS启动一个Activity的代码流程. 自己对Activity的启动过程也不是很了解,这里就初步做一个代码阅读笔记,为以后的迭代打下一个基础. 一.基础知识 在分析Activity的启动过程前,有必要先了解一下Activity相关的基础知识. 1.Task和Activity的设计理念 关于Android中Task和Activity的介绍,个人觉得<深入理解Android>中的例子不错. 我们就借鉴其中的例子,进行相应的说明: 上图列出了用户在Android系统上

3.1 启动 Activity

不同于使用 main() 方法启动应用的其他编程范例,Android 系统会通过调用对应于其生命周期中特定阶段的特定回调方法在 Activity 实例中启动代码.有一系列可启动 Activity 的回调方法,以及一系列可分解 Activity 的回调方法. 本课程概述了最重要的生命周期方法,并向您展示如何处理创建 Activity 新实例的第一个生命周期回调. 了解生命周期回调 在 Activity 的生命周期中,系统会按类似于阶梯金字塔的顺序调用一组核心的生命周期方法. 也就是说,Activi

Android 启动Activity的方式

Activity的启动分为两种方式,显示方式和隐式方式,显示方式就是在通过intent启动Activity时指定了Activity的包名和类名, 而隐式方式则在初始化Intent时只指定action或action和data属性.接下来将来总结显示启动和隐式启动的方式和注意事项. 1.Activity的显示启动:通过包名来启动(不管是启动自己应用的Activity还是启动其他应用的Activity) 1.1 ComponentName对象的方式 ComponentName cn = new Com

Java 方法调用

在调用方法时,程序的执行流程会进入方法的内部,当执行到方法内部的return语句或执行完方法内部的代码以后,则返回到调用该方法的位置继续向下执行. 方法调用的语法分为以下两种: 1.一个类内部的方法调用:指调用以及被调用的方法都在一个类的内部. 2.不同类之间的方法调用:指调用以及被调用的方法位于不同的类内部. 一个类内部方法调用语法 在进行方法调用时,调用的语法格式和static修饰符有关,所以按照一个方法在声明时是否有static修饰分为两类: (1)有static修饰的称作静态方法(2)没

Android 跨进程启动Activity黑屏(白屏)的三种解决方案

原文链接:http://www.cnblogs.com/feidu/p/8057012.html 当Android跨进程启动Activity时,过程界面很黑屏(白屏)短暂时间(几百毫秒?).当然从桌面Lunacher启动一个App时也会出现相同情况,那是因为App冷启动也属于跨进程启动Activity.为什么没会出现这种情况呢?真正元凶就是Android创建进程需要准备很多资源,它是一个耗时的操作. 黑屏(白屏)原因 当A进程启动B进程中的一个Activity时,Android系统会先有zygo

Activity的生命周期与加载模式(一)

Activity是android应用最重要的组成单元之一(另外三个是Service.BroadcaseReceiver.ContentProvider),Activity的功能是向用户呈现不同的操作界面.一个android应用通常有多个activity组成activity栈,当前活动的activity位于栈顶. 当Activity处于Android应用中运行时,同样受系统控制有其自身的生命周期. 下面详细介绍Android的生命周期: ***总结起来大致有4个状态*** 活动状态:当前的Acti

Android app启动activity并调用onCreate()方法时都默默地干了什么?

Android app启动activity并调用onCreate() 方法时都默默地干了什么? 在AndroidManifest.xml文件中的<intent-filter>元素中有这么两句: <intent-filter>     <action android:name="android.intent.action.MAIN"/>     <category android:name="android.intent.categor