【问题标题】:Why is the fragment's setRetainInstance(true) method not working?为什么片段的 setRetainInstance(true) 方法不起作用?
【发布时间】:2013-08-27 15:38:39
【问题描述】:

我无法让我的 Fragment 在方向更改时保留其实例。

活动类

public class MyActivity extends Activity
{
   private MyFragment fragment;

   public void onCreate(Bundle savedInstanceState)
   {
       if(savedInstanceState == null)
       {
           fragment = new MyFragment();
       }

       //null pointer exception on this line of code. fragment not being retained. 
       getFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
   } 
}

片段类

public class MyFragment extends Fragment
{ 
    private View view;
    private CustomListViewAdapter adapter;
    public ArrayList<HashMap<String, String>> arrHashMap;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        view = inflater.inflate(R.layout.fragment_screen, container, false);

        if(arrHashMap != null)
        {
            ListView lv = (ListView) view.findViewById(R.id.fragment_lv);
            adapter = new CustomListViewAdapter( (MyActivity)getActivity() , arrHashMap);
            lv.setAdapter(adapter);
            lv.setOnItemClickListener((MyActivity)getActivity());
        }
        else
        {
            /* some code to create arrHashMap variable

            */
            ListView lv = (ListView) view.findViewById(R.id.fragment_lv);
            adapter = new CustomListViewAdapter( (MyActivity)getActivity() , arrHashMap);
            lv.setAdapter(adapter);
            lv.setOnItemClickListener((MyActivity)getActivity());
        }

        return(view);
    }

    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);
        setRetainInstance(true);
    }
}

尽管在 onActivityCreated 中设置了 setRetainInstance(true),但在方向更改时,MyFragment 仍为空。创建 MyActivity 时,也会始终重新创建 MyFragment。另外,我知道 setRetainInstance(true) 不适用于 UI 片段,但是,我没有使用保存的适配器或视图成员变量,我只是在方向更改时重用保留的 arrHashMap 变量,因此我可以重新创建适配器并更改 UI。

【问题讨论】:

    标签: android android-fragments null fragment orientation-changes


    【解决方案1】:

    更新:我决定根本不使用 setRetainInstance(true),我使用 ObjectInputStream 和 ObjectOutputStream 类解决了问题,并将 arrHashMap 对象保存到 MyActivity 的 onSaveInstanceState(Bundle outState) 方法中的文件中,并检索了 arrHashMap在 MyActivity 的 onRestoreInstanceState(Bundle savedInstanceState) 方法中来自该文件的对象。然后我继续使用检索到的 arrHashMap 对象设置适配器。

    作为补充说明,我将 MyFragment 的 arrHashMap 实例变量更改为静态变量,以便可以从 MyActivity 访问它。

    保存代码:

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
    
        try
        {
            File f = new File( this.getDir("myDir", Context.MODE_PRIVATE), "arrHashMap");
            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(f));
            os.writeObject(MyFragment.arrHashMap);
            os.flush();
            os.close();
        }
        catch(IOException e)
        {
            return;
        }
    }
    

    恢复代码:

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState)
    {
        super.onRestoreInstanceState(savedInstanceState);        
    
        ArrayList<HashMap<String,String>> arrHashMap;
        try
        {
            File f = new File( this.getDir("myDir", Context.MODE_PRIVATE), "arrHashMap");
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(f));
            arrHashMap =  ((ArrayList<HashMap<String, String>>) is.readObject() );
            is.close();
        }
        catch (Exception e)
        {
            arrHashMap = null;
        }
        if(arrHashMap != null)
        {
            ListView lv = (ListView)findViewById(R.id.fragment_lv);
            CustomListViewAdapter adapter = new CustomListViewAdapter(this, arrHashMap);
            lv.setAdapter(adapter);
            lv.setOnItemClickListener(this);
        }
    }
    

    【讨论】:

      【解决方案2】:

      有点晚了,我希望这对您将来有所帮助,但您的问题在于

      if(savedInstanceState == null)
             {
                 fragment = new MyFragment();
             }
      getFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
      

      setRetainInstance 表示当应用旋转时,fragment 不会被重新创建,activity 仍然会被重新创建并且不会持有对它的引用

      所以当活动旋转并检查savedInstanceState == null 时,它不会创建片段,因此没有对它的引用

      如果你想回去修复它,它应该是这样的(这不是我的想法,所以可能存在一些错误)

      首先创建一个表示片段的常量字符串,如下所示:

      private static final String FRAGMENT = "myFragmentTag";
      

      然后在初始化

      if (savedInstanceState == null) {
          fragment = new MyFragment();
          getFragmentManager().beginTransaction().replace(R.id.fragment_container,fragment,FRAGMENT).commit()
      } else
          fragment = getFragmentManager().findFragmentByTag(FRAGMENT)
      

      基本上,当您创建活动时,您会生成片段,而当您旋转它时,您会从片段管理器中获取现有片段

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多