1、 需求
在实际开发中我们可能会有这样的需求,比如:通过startActivityForResult,之后需要通过protected void onActivityResult(int requestCode, int resultCode, Intent data)方法来获取启动的Activity返回的值。这样用起来不是很方便,有没有方法可以直接通过回调来获取返回的值呢?哈哈是有的
2、 思路分析
除了Activity有onActivityResult方法,Fragment也有,那么我们是不是可以通过实例化一个Fragment对象让它去处理这个回调呢?下面让我们看代码是如何实现的,以及实现的过程中需要注意的地方。
3、 实现代码
3.1 定义一个Fragment
public class InvisibleFragment extends Fragment {
private final int OPEN_ACTIVITY = 10000;
AuthCallBack callBack;
public void startActivity(Activity context, String accessToken, AuthCallBack callBack) {
this.callBack=callBack;
Intent intent = new Intent();
...
startActivityForResult(intent, OPEN_ACTIVITY);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (null == data) {
return;
}
if (requestCode == OPEN_ACTIVITY) {
callBack.result(data...);
}
}
}
3.2、实例化Fragment并跟Activity绑定
private InvisibleFragment getInvisibleFragment(Activity activity) {
FragmentManager fragmentManager = activity.getFragmentManager();
Fragment existedFragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG);
if (existedFragment != null) {
return (InvisibleFragment) existedFragment;
} else {
InvisibleFragment invisibleFragment = new InvisibleFragment();
fragmentManager.beginTransaction().add(invisibleFragment, FRAGMENT_TAG).commit();
fragmentManager.executePendingTransactions();
return invisibleFragment;
}
}
注意这里的
fragmentManager.beginTransaction().add(invisibleFragment, FRAGMENT_TAG).commit();fragmentManager.executePendingTransactions();
如果是commit()就要跟executePendingTransactions一起使用,当然也可以用commitNow()(API>=24才支持)就不用跟executePendingTransactions一起使用了。否则会报Fragment not attached 通 activity这样的错误。
commit(), commitNow() 和 executePendingTransactions()
使用commit()的时候, 一旦调用, 这个commit并不是立即执行的, 它会被发送到主线程的任务队列当中去, 当主线程准备好执行它的时候执行. popBackStack()的工作也是这样, 发送到主线程任务队列中去. 也即说它们都是异步的.
但是有时候你希望你的操作是立即执行的, 之前的开发者会在commit()调用之后加上 executePendingTransactions()来保证立即执行, 即变异步为同步. support library从v24.0.0开始提供了 commitNow()方法, 之前用executePendingTransactions()会将所有pending在队列中还有你新提交的transactions都执行了, 而commitNow()将只会执行你当前要提交的transaction. 所以commitNow()避免你会不小心执行了那些你可能并不想执行的transactions.
但是你不能对要加在back stack中的transaction使用commitNow(), 即addToBackStack()和commitNow()不能同时使用. 为什么呢? 想想一下, 如果你有一个提交使用了commit(), 紧接着又有另一个提交使用了commitNow(), 两个都想加入back stack, 那back stack会变成什么样呢? 到底是哪个transaction在上, 哪个在下? 答案将是一种不确定的状态, 因为系统并没有提供任何保证来确保顺序, 所以系统决定干脆不支持这个操作.
前面提过popBackStack()是异步的, 所以它同样也有一个同步的兄弟popBackStackImmediate().
所以实际应用的时候怎么选择呢?
如果你需要同步的操作, 并且你不需要加到back stack里, 使用commitNow(). support library在FragmentPagerAdapter里就使用了commitNow()来保证在更新结束的时候, 正确的页面被加上或移除.
如果你操作很多transactions, 并且不需要同步, 或者你需要把transactions加在back stack里, 那就使用commit().
如果你希望在某一个指定的点, 确保所有的transactions都被执行, 那么使用executePendingTransactions().
3.3、调用
getInvisibleFragment(context).startActivity(activity,"", new AuthCallBack() { @Override public void result(String data) { //显示回调结果 } });
4、 总结
这种方法就是利用了Fragment可实例化并attached到Activity做了数据的关联,其实还可以用这种思路封装下权限认证管理的,直接一个任务链模式就可以搞定不用那么麻烦的处理,这样的思路简化了调用的代码,大家可以尝试手动写起来试试,有问题欢迎大家拍砖!哈哈,欢迎留言交流。
关注我获取更多知识或者投稿