Android关于Intent的思考:如何更好的启动一个Activity
普通写Intent的方法和缺陷
- 普通Activity A要调用起Activity B页面会这么写:
Activity A:
Intent intent = new Intent(A.this, B.class);intent.putExtra("is_index", message);startActivity(intent);
Activity B:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... String is_index = getIntent().getExtras().getString("is_index"); ...}
- 上面的写法是大多数Intent写法,在发起方创建intent。但这种写法在代码量大大增加的时候会出现一个问题。当Activity B在各种地方都会被调用起的时候,并且会传入各种各样不同的extra字段时,会发现很混乱,哪些发起方使用了哪些extra字段,每个字段什么意思,哪些是必须的等等问题。最终造成B代码可读性变差,让以后想要调用起B的页面也不清楚需要传入哪些extra。
优化写Intent
- 同样是Activity A要调用起Activity B页面的例子:
Activity A:
Intent intent = B.newIndexIntent(this, message);startActivity(intent);
Activity B:
private final static String IS_INDEX = "is_index";@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... String is_index = getIntent().getExtras().getString(IS_INDEX); ...}.../** * 创建intent * is_index 是否是首页跳转过来的 */public static Intent newIndexIntent(Context context, String message) { Intent newIntent = new Intent(context, b.class); newIntent.putExtra(IS_INDEX, message); return newIntent;}
- 用上面的方法可以保证所有extra全部定义在被调用起Activity的内部,对外不可见,并可以对每个extra有详细的注释(是否必须、在什么地方调用等)。
思考
- 跳转的时候是否可以直接写为 B.newIndexIntent(this,text),因为 发起启动的不是界面,而是上下文对象。是否可以直接做B.class里面封装一个启动方法,里面接受几个参数,然后用传过来的context启动。但有一些特殊情况,如:启动时为startActivityForResult,result的值最好还是放在启动的类里定义等。
附录
- Intent中的各种FLAG
Intent intent = new Intent(this,xxx.class); //如果activity在task存在,拿到最顶端,不会启动新的Activity intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); //如果activity在task存在,将Activity之上的所有Activity结束掉 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); //默认的跳转类型,将Activity放到一个新的Task中 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //如果Activity已经运行到了Task,再次跳转不会在运行这个Activity intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
网上有关于Intent flag和taskAffinity的实验结果, 我们来看下相关结论:
FLAG_ACTIVITY_NEW_TASK并不像官方文档所说的等同与singleTask.
在没有任何其他flag组合和taskAffinity设置的情况下, 同一应用内FLAG_ACTIVITY_NEW_TASK启动另外一个Activity, 不会在新的Task中创建实例, 也不会有实例复用.
FLAG_ACTIVITY_SINGLE_TOP作用等同与singleTop, 当Task的top Activity是该Activity时, Activity复用.
FLAG_ACTIVITY_CLEAR_TOP会clear top, 也就是说如果Task中有ABCD, 在D中启动B, 会clear掉B以上的CD. CD销毁.
注意, FLAG_ACTIVITY_CLEAR_TOP并不意味着重用, 默认Activity为standard模式的话, 只是会clear其top的其他Activity实例, 该Activity并不会重用, 而是也会销毁, 然后创建一个新的该Activity实例来响应此Intent.
在没有设置taskAffinity的情况下, 同一应用内FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TOP组合启动另外一个Activity, 作用和单独使用FLAG_ACTIVITY_CLEAR_TOP是一样.(此点类同与第二点)
如taskAffinity解释的一样, 在我们没有引入taskAffinity时(android:affinity=xxx.xxx.xxx), 同一个应用中, 使用各种Intent flag都并不会创建新的Task.
taskAffinity需结合FLAG_ACTIVITY_NEW_TASK使用, 此时会再新的Task中寻找/创建待启动的Activity实例.
强烈建议 FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TOP结合使用,单独使用FLAG_ACTIVITY_NEW_TASK可能会遇到问题(系统会在android:affinity=xxx.xxx.xxx的Task中找有没有已经存在的A的实例, 发现Task中有. 于是乎, 想重用A. 然而并没有能销毁B, 让A弹出来接收新的Intent.所以说, 这种情况下, Intent.FLAG_ACTIVITY_NEW_TASK必须结合Intent.FLAG_ACTIVITY_CLEAR_TOP来一起用)。
Intent Flag并不能代替launchMode, 至少在想重用Activity的情况下, 你需要做的是考虑launchMode而非Intent Flag.
个人理解, Intent Flag更多是倾向于用来做Task中的Activity组织. 而launchMode兼顾Task组织和Activity实例的重用.
更多相关文章
- Android改变ExpandableListView的indicator图标实现方法
- Android(安卓)中在有序广播中添加自定义权限的实例
- Android通过访问网页查看网页源码实例详解
- Android(安卓)webService访问实例
- 如何避免打开键盘或横竖屏切换,active重启,处理界面的延迟动画
- AndroidManiFast 字段意义
- Rokon引擎主要类介绍
- Android(安卓)Studio使用---一些奇葩但有用的用法
- [Android实例] webview 实现翻页功能