国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android解惑 - 為什么要用Fragment.setArguments(Bundle bundle)來傳遞參數(shù)

2019-11-09 17:51:39
字體:
供稿:網(wǎng)友
Fragment在Android3.0開始提供,并且在兼容包中也提供了Fragment特性的支持。Fragment的推出讓我們編寫和管理用戶界面更快捷更方便了。但當(dāng)我們實(shí)例化自定義Fragment時(shí),為什么官方推薦Fragment.setArguments(Bundle bundle)這種方式來傳遞參數(shù),而不推薦通過構(gòu)造方法直接來傳遞參數(shù)呢?為了弄清這個(gè)問題,我們可以做一個(gè)測試,分別測試下這兩種方式的不同首先,我們來測試下通過構(gòu)造方法傳遞參數(shù)的情況[java] view plain copy 在CODE上查看代碼片public class FramentTestActivity extends ActionBarActivity {            @Override      可以看到我們傳遞過來的數(shù)據(jù)正確的顯示了,現(xiàn)在來考慮一個(gè)問題,如果設(shè)備配置參數(shù)發(fā)生變化,這里以橫豎屏切換來說明問題,顯示如下發(fā)生了什么問題呢?我們傳遞的參數(shù)哪去了?為什么會(huì)顯示默認(rèn)值?不急著討論這個(gè)問題,接下來我們來看看Fragment.setArguments(Bundle bundle)這種方式的運(yùn)行情況[java] view plain copy 在CODE上查看代碼片public class FramentTest2Activity extends ActionBarActivity {                   @Override          protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);               setContentView(R.layout. activity_main);                  if (savedInstanceState == null) {                      getSupportFragmentManager().beginTransaction()                                   .add(R.id. container, TestFragment.newInstance("param")).commit();               }           }            public static class TestFragment extends Fragment {                  private static final String ARG = "arg";                               public TestFragment() {                      Log. i("INFO", "TestFragment non-parameter constructor" );               }                  public static Fragment newInstance(String arg){                      TestFragment fragment = new TestFragment();                      Bundle bundle = new Bundle();                      bundle.putString( ARG, arg);                      fragment.setArguments(bundle);                       return fragment;               }                               @Override                public View onCreateView(LayoutInflater inflater, ViewGroup container,                             Bundle savedInstanceState) {                      View rootView = inflater.inflate(R.layout. fragment_main, container,                                    false);                      TextView tv = (TextView) rootView.findViewById(R.id. tv);                      tv.setText(getArguments().getString( ARG));                       return rootView;               }         }    }  我們再來看看橫豎屏切換后的運(yùn)行情況看到了吧,我們傳遞的參數(shù)在橫豎屏切換的情況下完好保存了下來,正確的顯示給用戶那么這到底是怎么回事呢,我們知道設(shè)備橫豎屏切換的話,當(dāng)前展示給用戶的Activity默認(rèn)情況下會(huì)重新創(chuàng)建并展現(xiàn)給用戶,那依附于Activity的Fragment會(huì)進(jìn)行如何處理呢,我們可以通過源碼來查看先來看看Activity的onCreate(Bundle saveInstance)方法[java] view plain copy 在CODE上查看代碼片 protected void onCreate(Bundle savedInstanceState) {      if (DEBUG_LIFECYCLE ) Slog.v( TAG, "onCreate " + this + ": " + savedInstanceState);      if (mLastNonConfigurationInstances != null) {          mAllLoaderManagers = mLastNonConfigurationInstances .loaders ;      }      if (mActivityInfo .parentActivityName != null) {          if (mActionBar == null) {              mEnableDefaultActionBarUp = true ;          } else {              mActionBar .setDefaultDisplayHomeAsUpEnabled( true);          }      }      if (savedInstanceState != null) {          Parcelable p = savedInstanceState.getParcelable( FRAGMENTS_TAG );          mFragments .restoreAllState(p, mLastNonConfigurationInstances != null                  ? mLastNonConfigurationInstances .fragments : null);      }      mFragments .dispatchCreate();      getapplication().dispatchActivityCreated( this , savedInstanceState);      mCalled = true ;  }  由于我們的Fragment是由FragmentManager來管理,所以可以跟進(jìn)FragmentManager.restoreAllState()方法,通過對當(dāng)前活動(dòng)的Fragmnet找到下面的代碼塊[html] view%20plain copy   for (int i=0; i<fms.mActive.length; i++) {             FragmentState fs = fms.mActive[i];             if (fs != null) {                Fragment f = fs.instantiate(mActivity, mParent);                 if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);                 mActive.add(f);                 // Now that the fragment is instantiated (or came from being                 // retained above), clear mInstance in case we end up re-restoring                  // from this FragmentState again.                  fs.mInstance = null;             } else {                 mActive.add(null);                  if (mAvailIndices == null) {                      mAvailIndices = new ArrayList<Integer>();                 }                 if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);                 mAvailIndices.add(i);             }  }  接下來我們可以看看FragmentState.instantitate()方法的實(shí)現(xiàn)[html] view%20plain copy public Fragment instantiate(Activity activity, Fragment parent) {          if (mInstance != null) {              return mInstance ;          }                   if (mArguments != null) {              mArguments .setClassLoader(activity.getClassLoader());          }                   mInstance = Fragment.instantiate(activity, mClassName , mArguments );                   if (mSavedFragmentState != null) {              mSavedFragmentState .setClassLoader(activity.getClassLoader());              mInstance .mSavedFragmentState = mSavedFragmentState ;          }          mInstance .setIndex(mIndex , parent);          mInstance .mFromLayout = mFromLayout ;          mInstance .mRestored = true;          mInstance .mFragmentId = mFragmentId ;          mInstance .mContainerId = mContainerId ;          mInstance .mTag = mTag ;          mInstance .mRetainInstance = mRetainInstance ;          mInstance .mDetached = mDetached ;          mInstance .mFragmentManager = activity.mFragments;          if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,                  "Instantiated fragment " + mInstance );            return mInstance ;      }  可以看到最終轉(zhuǎn)入到Fragment.instantitate()方法[java] view%20plain copy 派生到我的代碼片public static Fragment instantiate(Context context, String fname, Bundle args) {     try {         Class<?> clazz = sClassMap .get(fname);         if (clazz == null) {             // Class not found in the cache, see if it's real, and try to add it             clazz = context.getClassLoader().loadClass(fname);             sClassMap .put(fname, clazz);         }         Fragment f = (Fragment)clazz.newInstance();         if (args != null) {             args.setClassLoader(f.getClass().getClassLoader());             f. mArguments = args;         }         return f;     } catch (ClassNotFoundException e) {         throw new InstantiationException( "Unable to instantiate fragment " + fname                 + ": make sure class name exists, is public, and has an"                 + " empty constructor that is public" , e);     } catch (java.lang.InstantiationException e) {         throw new InstantiationException( "Unable to instantiate fragment " + fname                 + ": make sure class name exists, is public, and has an"                 + " empty constructor that is public" , e);     } catch (IllegalaccessException e) {         throw new InstantiationException( "Unable to instantiate fragment " + fname                 + ": make sure class name exists, is public, and has an"                 + " empty constructor that is public" , e);     }  通過此方法可以看到,最終會(huì)通過反射無參構(gòu)造實(shí)例化一個(gè)新的Fragment,并且給mArgments初始化為原先的值,而原來的Fragment實(shí)例的數(shù)據(jù)都丟失了,并重新進(jìn)行了初始化通過上面的分析,我們可以知道Activity重新創(chuàng)建時(shí),會(huì)重新構(gòu)建它所管理的Fragment,原先的Fragment的字段值將會(huì)全部丟失,但是通過Fragment.setArguments(Bundle bundle)方法設(shè)置的bundle會(huì)保留下來。所以盡量使用Fragment.setArguments(Bundle bundle)方式來傳遞參數(shù)
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 永仁县| 留坝县| 上林县| 九龙坡区| 正定县| 青冈县| 府谷县| 东乡县| 高唐县| 丰镇市| 邵阳县| 冕宁县| 泾阳县| 西乌珠穆沁旗| 丘北县| 洞口县| 萍乡市| 卓尼县| 黄龙县| 三台县| 西华县| 临潭县| 奈曼旗| 尤溪县| 盐津县| 温州市| 松潘县| 宁武县| 固阳县| 翁牛特旗| 阳谷县| 肇源县| 新沂市| 五大连池市| 永兴县| 新宾| 浠水县| 会宁县| 临猗县| 辽宁省| 启东市|