旋转屏幕时保存Fragment状态

8
我正在为Android创建一个文件管理器应用程序,以下两个类包含了大部分的逻辑。在ContentList启动时,它将ContentListFragment添加到ContestList xml的容器布局中。通过添加ContentListFragment,我获取当前路径,然后调用setFileDir(String S),它基本上会获取传递路径处的文件,获取该位置的文件列表、初始化数组,然后初始化适配器。然后我设置适配器、设置操作栏UI和上下文操作栏。现在,每当ContentListFragment上的项目被按下时,它就会创建另一个ContentListFragment,使用所选项目的路径。然后将前面的fragment添加到后退堆栈中。这一切都很好,但问题出现在屏幕方向变化时。
在ContentListFragment的onCreate方法中设置setRetainInstance(true)是唯一防止整个应用程序在应用程序更改方向时强制关闭的方法。但是,这样做会导致在一段时间之后重新返回应用程序时应用程序崩溃(这是我遇到的主要问题,不知道原因)。
我尝试在Activity在方向改变时重新创建时用新的ContentListFragment替换当前ContentListFragment(下面没有代码),但是应用程序也会崩溃并显示NullPointerException错误,因此其他所有内容都会崩溃。
我该如何保存片段状态,以便在方向更改时一切保持不变,而且在一段时间后重新返回时不会强制关闭呢?
以防万一,我的应用程序只有一个Activity,并具有递归ContentListFragments。
public class ContentList extends DrawerActivity implements ContentListFragment.listFragmentListener{

    // instance variables
    private FragmentManager fm;
    private FragmentTransaction ft;
    private String currentPath;

    // Initializes variables.
    // If Activity is started for the first time, a path to the storage is
    // received.
    // Else, if it's an orientation change, the path is just retained.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_list);

        if (savedInstanceState == null) {
            fm = getSupportFragmentManager();
            ft = fm.beginTransaction();
            File file = Environment.getExternalStorageDirectory();
            currentPath = file.getPath();
            ft.add(R.id.content_container_fragment_listview, new ContentListFragment());
            ft.commit();
        } else {
            fm = getSupportFragmentManager();
            currentPath = savedInstanceState.getString("PATH");
        }
    }

    // Grabs the currentPath in case of orientation changes.
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("PATH", currentPath);
    }

dfsas

public class ContentListFragment extends SherlockListFragment {

    // instance variables
    private ArrayList<Item> items;
    private ArrayList<Item> copy_move_queue_items;
    private ItemAdapter adapter;
    private listFragmentListener lfListener;
    private String currentPath;
    private MenuItem menuItemRename;

    // instantiates variables using setFileDir() and the path from the container Activity.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        currentPath = ((ContentList) getActivity()).getCurrentPath();
        setFileDir(currentPath);

    }

    // Gets a reference to Activity interface
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            lfListener = (listFragmentListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + "must implement listFragmentListener");
        }
    }

    // Sets the UI of the listView and the ActionBar
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.content_list_fragment, container, false);

        File file = Environment.getExternalStorageDirectory();
        String rootPath = file.getPath();

        // Sets Action Bar title to current directory, and creates an Up
        // affordance if the root path doesn't equal the current Path
        getSherlockActivity().getSupportActionBar().setTitle(null);
        getSherlockActivity().getSupportActionBar().setLogo(R.drawable.ab_icon);

        if (currentPath.equals(rootPath)) {
            getSherlockActivity().getSupportActionBar()
                    .setDisplayHomeAsUpEnabled(false);
            getSherlockActivity().getSupportActionBar()
                    .setHomeButtonEnabled(false);
        } else {
            getSherlockActivity().getSupportActionBar()
                    .setDisplayHomeAsUpEnabled(true);



            // getSherlockActivity().getSupportActionBar().setTitle("/" +
            // (currentPath.substring(currentPath.lastIndexOf("/") +1)));
        }

        return v;

    }

    // Sets the long click Contextual Action Mode to the ListView
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setActionMode();
        setListAdapter(adapter);
    }
    // Gets the list of files at the path and adds them to the Item ArrayList,
// initializing the adapter as well
public void setFileDir(String path) {
    File file = new File(path);
    File[] files = file.listFiles();
    Arrays.sort(files, new fileComparator());
    items = new ArrayList<Item>();
    for (File f : files) {
        items.add(new Item(f));
    }
    adapter = new ItemAdapter(getActivity(), R.layout.content_list_item, items);
}
3个回答

16

这对我有用

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        onCreate(savedInstanceState);
    }

并且在您的活动标签内的清单文件中

android:configChanges="orientation|screenSize"


好的。我希望有人能解释一下为什么这个有效。 - TheRealChx101
这对我有用。在我的情况下,它只使用一个活动来实现片段。这是我所做的:
  1. 在清单中 android:configChanges="orientation|screenSize" // 我只有一个活动
@Override public void onViewStateRestored(@Nullable final Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); onCreate(savedInstanceState); }`
- blongho

15

使用此代码在屏幕旋转时保存 fragment 的状态。

onCreate(Bundle save)
{
   super.onCreate(save);
   setRetainInstance(true);
}

我之前没有注意到Fragment.setRetainInstance()的存在...这个API让生活变得非常容易! - Reuben Scratton
3
如果片段被添加到返回栈中,setRetainInstance(true)将不起作用。 - ovluca

0

由于这是工作和面试中面临的主要问题,因此我只是发布一下 :) 在API 13之前,我们使用的是已弃用的onRetainNonConfigurationInstance()方法(该方法与Activity相关,现在已移至Fragment),现在我们有了一个新方法,即setRetainInstance()(属于Fragment类的方法),它将保存片段的状态,即使在活动创建后也是如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接