巧妙的用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做了數據的關聯,其實還可以用這種思路封裝下權限認證管理的,直接一個任務鏈模式就可以搞定不用那麼麻煩的處理,這樣的思路簡化了調用的代碼,大家可以嘗試手動寫起來試試,有問題歡迎大家拍磚!哈哈,歡迎留言交流。

關注我獲取更多知識或者投稿

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章