Android开发日常,单个界面UI,单个界面业务,在需要的地方调用startActivity()
,App就可以蹦起来啦。多数时候,为了更好的用户体验,或者产品“合理”的想法,界面逻辑并不是乖巧的从A->B->C,再由C->B->A,而是,怎么说呢,只有你想不到,对!。在开发过程中,遇到这类问题,因此,稍加总结,希望能给阅读到此文的小伙伴一些帮助。
你可能遇到:
1. 界面由A->B->C->D->A,即D完成某一逻辑后,直接返回A。
2. 界面由A->B->C->D->(A->Z),这里返回A后立即启动Z。
3. Application类启动Activity。
文中可能出现错误,望阅读到的小伙伴及时指出,在核对后我会第一时间修改有误之处。
咋还没到正文呢,下面就是,从Activity的启动模式讲起。
Activity的四种启动模式
1. standard(默认)
2. singleTop(栈顶复用)
3. singleTask(栈内复用)
4. singleInstance (全局唯一)
standard是Activity的默认模式。如果你没有设置启动模式,系统会以该模式启动Activity。在该模式下,Activity每次启动,都会在当前任务栈生成一个新的实例。
singleTop模式,在该模式下,若要启动的Activity位于当前任务栈栈顶时,则不会再创建新的实例,直接就复用栈顶这个Activity,其回调方法onNewIntent()
会被执行。若需要启动的Activity不在栈顶或任务栈中并没有这个Activity存在,则会在栈顶创建一个新实例。
singleTask,在该模式下,若要启动的Activity在当前任务栈中不存在,则会在栈顶创建一个新实例。若存在,就会复用这个Activity,会将它上面的Activity全部出栈,其回调方法onNewIntent()
会被执行。
singleInstance,在该模式下,要启动的Activity会在一个新的任务栈中创建实例,这个新的任务栈只允许有这一个Activity存在,并且这个实例全局唯一,若再启动这个Activity,则会直接复用存在的实例,其回调方法onNewIntent()
会被执行。
我们可以在AndroidManifest.xml文件中设置Activity的启动模式。
这样:
<activity android:name=".testActivity" android:launchMode="singleTop" />
intent标记
启动模式可以帮助开发者更轻松的实现界面之间逻辑,但项目中,总是有力不从心的地方。怎么办呢,我们可以利用setFlags()
方法,为Intent的设置标记,一行代码,轻松跳转。
举个栗子:
Intent nextActivityIntent = new Intent(this,NextActivity.class);
nextActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(nextActivityIntent);
Intent常用标记(我常用)
1. Intent.FLAG_ACTIVITY_SINGLE_TOP
2. Intent.FLAG_ACTIVITY_CLEAR_TOP
3 .Intent.FLAG_ACTIVITY_NEW_TASK
4. Intent.FLAG_ACTIVITY_CLEAR_TASK
FLAG_ACTIVITY_SINGLE_TOP,若要启动的Activity位于当前任务栈栈顶时,则不会再创建新的实例。
FLAG_ACTIVITY_CLEAR_TOP ,若当前栈中存在要启动的Activity实例,会将它上面的Activity全部出栈。
FLAG_ACTIVITY_NEW_TASK,要启动的Activity会在一个新的任务栈中创建实例。
FLAG_ACTIVITY_CLEAR_TASK,这个标记必须和FLAG_ACTIVITY_NEW_TASK一起使用,要启动的Activity会在一个新任务栈创建实例,所有旧的Acitivity都会被干掉。
以上仅为我常用的标记,联合使用,功能强大。
startActivity方法
若仅是启动单个界面,可以调用startActivity()
方法,若要启动多个界面,就要用到startActivities()
方法,后者须传入Intent[]参数,这里注意插入Intent[]中Intent顺序,先启动的Activiity会先压入任务栈中。
上码
1. 界面由A->B->C->D->A,即D完成某一逻辑后,直接返回A
D中返回A方法如下:
private void backA() {
Intent backAIntent = new Intent(this, AActivity.class);
backAIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(backAIntent);
}
其中FLAG_ACTIVITY_SINGLE_TOP 和FLAG_ACTIVITY_CLEAR_TOP一起使用,A上面BCD会全部出栈,A来到栈顶,A的回调方法onNewIntent()
会被执行,这里仅Toast—“Welcome back to A”。
A中代码如下:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Toast.makeText(this, "Welcome back to A", Toast.LENGTH_SHORT).show();
}
运行效果:
2. 界面由A->B->C->D->(A->Z),这里返回A后立即启动Z
可以修改AonNewIntent()
方法中代码。
这样:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Intent ZIntent = new Intent(this, ZActivity.class);
startActivity(ZIntent);
}
可以修改DbackA()
方法中代码。
这样:
private void backA() {
Intent[] intents = new Intent[2];
intents[0] = new Intent(this, AActivity.class);
intents[0].setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intents[1] = new Intent(this, ZActivity.class);
startActivities(intents);
}
两种方法略有区别,这里不做详细讨论。
运行效果:
3. 非 Activity Context启动Activity
先上效果:
可以看到,界面由A->B,B界面返回退出App,没有回到A,这里给Intent设置了FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TASK两个标记,这样,B界面会在新的任务栈创建实例,旧的Activity全部被干掉,因此B返回,直接退出App。若只设置FLAG_ACTIVITY_NEW_TASK标记,B界面返回到A。
非 Activity Context启动Activity,必须为Intent设置FLAG_ACTIVITY_NEW_TASK标记,否则会报错。
这样(脑补颜色全红!!!):
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
最后
开发是一个团队相互协作,队友会调用你开发的模块,你也会调用队友的模块。我们可以在Activity中添加静态启动方法。
举个例子:
public static void start(Context context, int paramOne, String paramTwo) {
Intent intent = new Intent(context, AActivity.class);
intent.putExtra("paramOne", paramOne);
intent.putExtra("paramTwo", paramTwo);
context.startActivity(intent);
}
这样调用者根据方法传入相应参数即可,减少团队不必要沟通,这样开发者若修改此方法(增加或删除参数),可以迅速定位,统一修改。着实是一个非常实用的小技巧。
第一篇博客,就这样吧。