启动Activity的几种方式
启动Activity一般借助Intent,不仅可以启动本应用内的Activity,还可以启动第三方应用的Activity。启动还可以给Intent加上指定的flag,参考Activity启动的Flag。
1、Intent显示启动
一般启动本应用内的Activity可以使用这种方式,因为知道类名。显示启动也有多种方式,不过变来变去都一样。创建启动Activity用到的Intent最直接简洁的一种方式如下:
Intent intent = new Intent(this, SettingsActivity.class);
另一种方式:
Intent intent = new Intent();
intent.setClass(this,SettingsActivity.class);
还有一种:
Intent intent = new Intent();
ComponentName componentName = new ComponentName(this, SettingsActivity.class);
intent.setComponent(componentName);
虽然显示Intent的创建方式这么多,但是查看源码不难发现最终都一样。借助内部的private ComponentName mComponent对象。
第一张方式的源码,内部构造函数直接创建一个ComponentName对象:
public Intent(Context packageContext, Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
} 第二种创建一个空的Intent在setClass:
public @NonNull Intent setClass(@NonNull Context packageContext, @NonNull Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
return this;
} 第三中方式更是多此一举,创建一个ComponentName对象,再赋值给Intent成员变量:
public @NonNull Intent setComponent(@Nullable ComponentName component) {
mComponent = component;
return this;
}
2、隐式Intent启动:Action
一般用来启动第三方APP的Activity页面。隐式启动Activity需要在AndroidManifest.xml文件中对应Activity节点下配置要启动Activity的action和category。如果知道第三方APP特定Activity页面的action就可以启动它。
AndroidManifest.xml中Activity节点下配置action和category,两个都需配置才有效。
<activity
android:name=".activity.ITheme"
android:label="i主题">
<intent-filter>
<action android:name="com.vivo.action.theme.onlinepreview" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
①方式一:创建一个空的Intent,添加action和category。
Intent intent = new Intent();
intent.setAction("com.test.action");
intent.addCategory("com.test.category"); 源码:
public @NonNull Intent setAction(@Nullable String action) {
mAction = action != null ? action.intern() : null;
return this;
}
public @NonNull Intent addCategory(String category) {
if (mCategories == null) {
mCategories = new ArraySet<String>();
}
mCategories.add(category.intern());
return this;
} ②方式二:创建Intent的时候传入action。
Intent intent = new Intent("com.test.action"); 源码:
public Intent(String action) {
setAction(action);
}
如果多个Activity具有相同的Action,那么通过Action隐式启动Activity,系统会先弹出应用选择对话框:
<activity
android:name=".activity.ITheme"
android:label="i主题">
<intent-filter>
<action android:name="com.vivo.action.theme.onlinepreview" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.ITheme"
android:label="i主题">
<intent-filter>
<action android:name="com.vivo.action.theme.onlinepreview" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

3、ComponentName
ComponentName:可以启动其他应用的Activity、Service。创建一个空的Intent,在创建一个ComponentName对象,设置给Intent对象即可。
ComponentName chatActivity =new ComponentName(param1,param2);
//param1:Activity、Service所在应用的包名
//param2:Activity、Service的包名+类名
示例:
ComponentName componentName = new ComponentName("com.vivo.reply","com.vivo.reply.activity.ITheme");
intent.setComponent(componentName);
startActivity(intent); 注意第三方的Activity在Manifest.xml中应该将属性android:exported设置为true,对外暴露:
<activity android:name=".activity.ITheme
android:exported="true"/>
用这种方式启动需要注意如果目标APP没有安装,不存在指定的Activity会异常:
E AndroidRuntime: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.reply/com.reply.activity.Theme}; have you declared this activity in your AndroidManifest.xml?
E AndroidRuntime: at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2056)
E AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1716)
E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:5252)
E AndroidRuntime: at d.k.a.c.startActivityForResult(:676)
E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:5210)
E AndroidRuntime: at d.k.a.c.startActivityForResult(:663)
E AndroidRuntime: at android.app.Activity.startActivity(Activity.java:5581)
4、startActivity()
最后调用Context中的startActivity(Intent intent)方法启动Activity。
如果使用Activity的startActivity方法,不会有任何限制,因为Activity继承自Context,重载了startActivity方法。
startActivity(intent);
Content中的startActivity方法,需要开启一个新的task。
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);