亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

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

2019-11-09 17:51:39
字體:
來源:轉載
供稿:網友
Fragment在Android3.0開始提供,并且在兼容包中也提供了Fragment特性的支持。Fragment的推出讓我們編寫和管理用戶界面更快捷更方便了。但當我們實例化自定義Fragment時,為什么官方推薦Fragment.setArguments(Bundle bundle)這種方式來傳遞參數,而不推薦通過構造方法直接來傳遞參數呢?為了弄清這個問題,我們可以做一個測試,分別測試下這兩種方式的不同首先,我們來測試下通過構造方法傳遞參數的情況[java] view plain copy 在CODE上查看代碼片public class FramentTestActivity extends ActionBarActivity {            @Override      可以看到我們傳遞過來的數據正確的顯示了,現在來考慮一個問題,如果設備配置參數發生變化,這里以橫豎屏切換來說明問題,顯示如下發生了什么問題呢?我們傳遞的參數哪去了?為什么會顯示默認值?不急著討論這個問題,接下來我們來看看Fragment.setArguments(Bundle bundle)這種方式的運行情況[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;               }         }    }  我們再來看看橫豎屏切換后的運行情況看到了吧,我們傳遞的參數在橫豎屏切換的情況下完好保存了下來,正確的顯示給用戶那么這到底是怎么回事呢,我們知道設備橫豎屏切換的話,當前展示給用戶的Activity默認情況下會重新創建并展現給用戶,那依附于Activity的Fragment會進行如何處理呢,我們可以通過源碼來查看先來看看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來管理,所以可以跟進FragmentManager.restoreAllState()方法,通過對當前活動的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()方法的實現[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 ;      }  可以看到最終轉入到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);     }  通過此方法可以看到,最終會通過反射無參構造實例化一個新的Fragment,并且給mArgments初始化為原先的值,而原來的Fragment實例的數據都丟失了,并重新進行了初始化通過上面的分析,我們可以知道Activity重新創建時,會重新構建它所管理的Fragment,原先的Fragment的字段值將會全部丟失,但是通過Fragment.setArguments(Bundle bundle)方法設置的bundle會保留下來。所以盡量使用Fragment.setArguments(Bundle bundle)方式來傳遞參數
上一篇:學習Android廣播小結

下一篇:Android Vector

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精品小视频| 久久久精品999| 亚洲美女精品成人在线视频| 精品国内产的精品视频在线观看| 国产v综合v亚洲欧美久久| 91精品国产综合久久男男| 992tv成人免费影院| 亚洲欧美综合另类中字| 国产成人精品在线播放| 国产精品久久一| 91精品在线一区| 欧美老女人bb| 91最新国产视频| 欧美多人乱p欧美4p久久| 亚洲久久久久久久久久久| 欧美激情喷水视频| 成人国产精品色哟哟| 亚洲色图综合久久| 国产视频精品一区二区三区| 久久亚洲欧美日韩精品专区| 欧美老少做受xxxx高潮| 国产精品老牛影院在线观看| 久久亚洲精品视频| 欧美日韩一二三四五区| 亚洲毛片在线免费观看| 欧美日韩中国免费专区在线看| 超在线视频97| 国产精品99久久久久久久久久久久| 亚洲欧洲国产一区| 热久久这里只有| 92福利视频午夜1000合集在线观看| 欧美在线免费视频| 欧美重口另类videos人妖| 亚洲欧洲午夜一线一品| 日韩国产激情在线| 欧美激情一区二区三区高清视频| 亚洲自拍小视频| 午夜精品久久17c| 国产一级揄自揄精品视频| 国产精品青草久久久久福利99| 亚洲成人免费网站| 午夜精品一区二区三区在线视频| 91国自产精品中文字幕亚洲| 日韩av中文字幕在线免费观看| 97精品国产91久久久久久| 亚洲欧洲第一视频| 日韩欧美成人精品| 国产香蕉97碰碰久久人人| 久久香蕉频线观| 国产精品青青在线观看爽香蕉| 中文字幕亚洲一区在线观看| 伊人久久综合97精品| 日韩av影视综合网| 国产精品96久久久久久又黄又硬| 91高潮在线观看| 国产日本欧美一区二区三区| 久久国产精品久久国产精品| 色午夜这里只有精品| 欧美成人精品一区二区三区| 影音先锋欧美精品| 伊人青青综合网站| 久久91亚洲人成电影网站| 亚洲免费视频观看| 91tv亚洲精品香蕉国产一区7ujn| 在线视频日本亚洲性| 久久久久久亚洲精品中文字幕| 精品偷拍一区二区三区在线看| 亚洲另类图片色| 国产精品视频99| 高清一区二区三区日本久| 91亚洲精华国产精华| 国产成人精品综合久久久| 成人精品在线观看| 亚洲欧美中文另类| 性色av香蕉一区二区| 欧美精品18videos性欧| 亚洲人成伊人成综合网久久久| 97成人精品视频在线观看| 中文字幕亚洲欧美日韩在线不卡| 国产精品白嫩初高中害羞小美女| 久久久久久久国产精品| 青青久久av北条麻妃海外网| 日韩中文在线中文网三级| 国产午夜精品免费一区二区三区| 久久在线免费观看视频| 亚洲最大在线视频| 久久久精品一区二区三区| 韩国精品久久久999| 中文字幕在线国产精品| 久久久久久久久久久人体| 日韩视频欧美视频| 亚洲japanese制服美女| 最新69国产成人精品视频免费| 亚洲视频日韩精品| 欧洲成人免费视频| 久久免费视频网| 中文字幕免费国产精品| 色综合久久精品亚洲国产| 国产精品∨欧美精品v日韩精品| 国产精品99久久久久久久久久久久| 中文字幕日韩在线视频| 在线观看久久久久久| 狠狠躁夜夜躁人人爽天天天天97| 69精品小视频| 国产精品久久久久久久美男| 精品中文字幕在线2019| 国产欧美精品日韩| 国产精品久久久久国产a级| 国产亚洲精品久久久久久| 欧美日韩一区二区三区| 这里只有精品久久| 久久久精品久久久| 国产精品流白浆视频| 久久久精品久久久久| 51色欧美片视频在线观看| 国产欧美精品日韩| 91在线高清视频| 欧美丰满少妇xxxxx| 一区二区三区www| 国产美女久久久| 久久久久久久激情视频| 亚洲第一页中文字幕| 亚洲自拍偷拍网址| 日韩高清av一区二区三区| 91精品久久久久久久| 久久亚洲成人精品| 亚洲成人a级网| 91国内揄拍国内精品对白| 精品久久久在线观看| 欧美成人三级视频网站| 久久影视电视剧免费网站清宫辞电视| 亚洲精品大尺度| 欧美大片大片在线播放| 丝袜亚洲欧美日韩综合| 欧美激情亚洲综合一区| 久久精品成人欧美大片古装| 国产一区二区黑人欧美xxxx| 国产激情999| 久久av在线播放| 俺去亚洲欧洲欧美日韩| 欧美精品videos| 国产激情视频一区| 欧美日韩精品在线播放| 高跟丝袜欧美一区| 91精品久久久久久| 欧美大胆a视频| 成人激情视频免费在线| 久久夜色精品亚洲噜噜国产mv| 国产精品久久久久不卡| 黑人精品xxx一区一二区| 国产精品视频一区国模私拍| 激情亚洲一区二区三区四区| 中文字幕亚洲一区二区三区| 日韩美女在线看| 精品亚洲一区二区| 亚洲视频国产视频| 久久免费成人精品视频| 亚洲国产精品网站| 欧美在线视频一二三| 中日韩美女免费视频网站在线观看| 国产精品最新在线观看| 久久亚洲精品一区| 亚洲影院高清在线| 午夜精品视频网站|