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