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:

@Override
protected 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";

@Override
protected 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实例的重用.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值