Android Fragment 真正的完全解析(4)

运行时配置发生变化,最常见的就是屏幕发生旋转,如果你不知道如何处理屏幕变化可以参考:Android 屏幕旋转 处理 AsyncTask 和 ProgressDialog 的最佳方案 

这里提一下:很多人觉得强制设置屏幕的方向就可以了,但是有一点,当你的应用被至于后台(例如用户点击了home),长时间没有返回的时候,你的应用也会被重新启动。比如上例:如果你把上面的例子你至于FragmentThree界面,然后处于后台状态,长时间后你会发现当你再次通过home打开时,上面FragmentThree与FragmentOne叠加在一起,这就是因为你的Activity重新启动,在原来的FragmentThree上又绘制了一个FragmentOne。

好了,下面看一段代码:

Activity:

package com.zhy.zhy_fragments;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Window;

public class MainActivity extends Activity

{
 private FragmentOne mFOne;

@Override
 protected void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.activity_main);

mFOne = new FragmentOne();
  FragmentManager fm = getFragmentManager();
  FragmentTransaction tx = fm.beginTransaction();
  tx.add(R.id.id_content, mFOne, "ONE");
  tx.commit();

}

}

Fragment

package com.zhy.zhy_fragments;

import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragmentOne extends Fragment
{
 private static final String TAG = "FragmentOne";

@Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState)
 {
  Log.e(TAG, "onCreateView");
  View view = inflater.inflate(R.layout.fragment_one, container, false);
  return view;
 }

@Override
 public void onCreate(Bundle savedInstanceState)
 {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);

Log.e(TAG, "onCreate");
 }

@Override
 public void onDestroyView()
 {
  // TODO Auto-generated method stub
  super.onDestroyView();
  Log.e(TAG, "onDestroyView");
 }

@Override
 public void onDestroy()
 {
  // TODO Auto-generated method stub
  super.onDestroy();
  Log.e(TAG, "onDestroy");
 }

}

很简单的代码,当你运行之后,不断的旋转屏幕,你会发现每旋转一次屏幕,屏幕上就多了一个FragmentOne的实例,并且后台log会打印出许多套生命周期的回调。

类似:

07-20 08:18:46.651: E/FragmentOne(1633): onCreate
07-20 08:18:46.651: E/FragmentOne(1633): onCreate
07-20 08:18:46.651: E/FragmentOne(1633): onCreate
07-20 08:18:46.681: E/FragmentOne(1633): onCreateView
07-20 08:18:46.831: E/FragmentOne(1633): onCreateView
07-20 08:18:46.891: E/FragmentOne(1633): onCreateView

这是为什么呢,因为当屏幕发生旋转,Activity发生重新启动,默认的Activity中的Fragment也会跟着Activity重新创建;这样造成当旋转的时候,本身存在的Fragment会重新启动,然后当执行Activity的onCreate时,又会再次实例化一个新的Fragment,这就是出现的原因。

那么如何解决呢:

其实通过检查onCreate的参数Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建:

默认的savedInstanceState会存储一些数据,包括Fragment的实例:通过打印可以看出:

07-20 08:23:12.952: E/FragmentOne(1782): Bundle[{android:fragments=android.app.FragmentManagerState@40d0b7b8, android:viewHierarchyState=Bundle[{android:focusedViewId=2131230721, android:views=android.util.SparseArray@40d0af68}]}]

所以,我们简单改一下代码,只有在savedInstanceState==null时,才进行创建Fragment实例:

package com.zhy.zhy_fragments;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/3bd7bf90a93a91ebdc36edcde2b1c4df.html