巧妙的用Fragment实现回调 | 实现一波骚操作

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做了数据的关联,其实还可以用这种思路封装下权限认证管理的,直接一个任务链模式就可以搞定不用那么麻烦的处理,这样的思路简化了调用的代码,大家可以尝试手动写起来试试,有问题欢迎大家拍砖!哈哈,欢迎留言交流。

猜你喜欢

转载自blog.csdn.net/weixin_40611659/article/details/109091023
今日推荐