談談Fragment中的onActivityResult,onactivityresult
大家或許有遇到這個神坑,在Fragment中使用startActivityForResult能夠成功,可是在Fragment中的onActivityResult卻無法被調用。一不注意就讓人一夜愁白了頭。苦經探索(當然包括親愛的百度和Google),終於總結出了一些規律。
在Fragment中使用startActivityForResult之後,onActivityResult的調用是從activity中開始的(即會先調用activity中的onActivityResult)。
一.只嵌套了一層Fragment(比如activity中使用了viewPager,viewPager中添加了幾個Fragment)
在這種情況下要注意幾個點:
1.在Fragment中使用startActivityForResult的時候,不要使用getActivity().startActivityForResult,而是應該直接使startActivityForResult()。
2.如果activity中重寫了onActivityResult,那麼activity中的onActivityResult一定要加上super.onActivityResult(requestCode, resultCode, data)。
如果違反了上面兩種情況,那麼onActivityResult只能夠傳遞到activity中的,無法傳遞到Fragment中的。
沒有違反上面兩種情況的前提下,可以直接在Fragment中使用startActivityForResult和onActivityResult,和在activity中使用的一樣。
二.嵌套多層Fragment(比如activity中使用了viewPager,viewPager中添加了幾個Fragment,即第一層Fragment。其中一個Fragment又使用了一個ViewPager,這個ViewPager又加入了幾個Fragment,即第二層Fragment)
在這種情況下activity中的onActivityResult調用無法傳到第二層Fragment中。自己動手豐衣足食,我們只有手動傳了。
package neo.door.main;import java.util.List;import android.content.Intent;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentManager;import android.util.Log;public class MyBaseFragmentActivity extends FragmentActivity{ private String TAG="MyBaseFragmentActivity"; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); FragmentManager fragmentManager=getSupportFragmentManager(); for(int indext=0;indext<fragmentManager.getFragments().size();indext++) { Fragment fragment=fragmentManager.getFragments().get(indext); //找到第一層Fragment if(fragment==null) Log.w(TAG, "Activity result no fragment exists for index: 0x" + Integer.toHexString(requestCode)); else handleResult(fragment,requestCode,resultCode,data); } } /** * 遞迴調用,對所有的子Fragment生效 * @param fragment * @param requestCode * @param resultCode * @param data */ private void handleResult(Fragment fragment,int requestCode,int resultCode,Intent data) { fragment.onActivityResult(requestCode, resultCode, data);//調用每個Fragment的onActivityResult Log.e(TAG, "MyBaseFragmentActivity"); List<Fragment> childFragment = fragment.getChildFragmentManager().getFragments(); //找到第二層Fragment if(childFragment!=null) for(Fragment f:childFragment) if(f!=null) { handleResult(f, requestCode, resultCode, data); } if(childFragment==null) Log.e(TAG, "MyBaseFragmentActivity1111"); }}
讓activity繼承上面的MyBaseFragmentActivity 。這樣就手動把onActivityResult的調用傳遞到每一層的每一個Fragment裡面了。然後在每一個Fragment裡面重寫onActivityResult就行了,然後根據requestCode和resultCode來分別執行對應事件。
當然,不管是哪個Fragment調用startActivityForResult,onActivityResult的調用都會傳遞到每個Fragment中。
同樣需要注意:
1.如果activity中重寫了onActivityResult,那麼activity中的onActivityResult一定要加上super.onActivityResult(requestCode, resultCode, data),否則也無法傳進Fragment中。
不過有點值得注意的是:
在所有的Fragment中若是直接使用startActivityForResult(),那麼傳到activity中的onActivityResult中的requestCode就會不對,resultCode是對的,當然,這樣的話傳到每個Fragment中的onActivityResult的requestCode也是不對的。若是用getActivity().startActivityForResult,則傳出來的requestCode和rusultCode就都是對的。
當然若是直接按返回鍵返回,那麼會自動給一個resultCode,這個resultCode和我們設定的是不一樣的,因此在重寫onActivityResult的時候需要判定resultCode。
由於我們是手動將activity中的onActivityResult的調用傳進每一層的每一個Fragment中去的,所以不管在Fragment中是使用startActivityForResult(),還是使用getActivity().startActivityForResult,都沒關係,使用getActivity().startActivityForResult不會出現activity中onActivityResult中的調用無法傳進去的情況。會影響的只有requestCode。