Android 更改方向时保持列表片段选定项目位置

Android 更改方向时保持列表片段选定项目位置,android,android-fragments,Android,Android Fragments,我在另一个片段的左边有一个列表片段,基本上是标准的单击一个项目并更新右片段模式。当他们点击列表片段中的一个项目时,他们选择的是新闻文章类别,我需要保留他们旋转设备时选择的任何一个。我该怎么做?我当前的代码不起作用 我的代码如下: public class SideMenuFragment extends ListFragment { ArrayList<SideItem> sideItems; SideAdapter sideAdapter; public S

我在另一个片段的左边有一个列表片段,基本上是标准的单击一个项目并更新右片段模式。当他们点击列表片段中的一个项目时,他们选择的是新闻文章类别,我需要保留他们旋转设备时选择的任何一个。我该怎么做?我当前的代码不起作用

我的代码如下:

public class SideMenuFragment extends ListFragment {
    ArrayList<SideItem> sideItems;
    SideAdapter sideAdapter;
    public SideMenuFragment() {
        this.setRetainInstance(true);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.list, null);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        sideItems = new ArrayList<SideItem>();
                ...add bunch of items
        sideAdapter = new SideAdapter(getActivity(), sideItems);
        getListView().setVerticalScrollBarEnabled(false);
        setListAdapter(sideAdapter);
        if (savedInstanceState != null) {
            sideAdapter.setSelectedItem(savedInstanceState.getInt("sidePosition"));
            sideAdapter.notifyDataSetChanged();
                }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("sidePosition", sideAdapter.getSelectedItem());
    }

    @Override
    public void onListItemClick(ListView lv, View v, int position, long id) {
        if (sideAdapter.getSelectedItem() != position) {
            sideAdapter.setSelectedItem(position);
            sideAdapter.notifyDataSetChanged();
        }
        switch (position) {
                      ...switch the fragment depending on position.
                    }
    }

    // the meat of switching the above fragment
    private void switchFragment(Fragment fragment, String title) {
        if (getActivity() == null)
            return;
        if (getActivity() instanceof HomeActivity) {
            HomeActivity a = (HomeActivity) getActivity();
            a.switchContent(fragment, title);
        }
    }
}
公共类SideMenuFragment扩展了ListFragment{
ArrayList副项;
侧适配器侧适配器;
public SideMenuFragment(){
此.setRetainInstance(真);
}
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
返回充气机。充气(R.layout.list,空);
}
@凌驾
已创建ActivityState上的公共无效(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
sideItems=newArrayList();
…添加一堆项目
sideAdapter=新的sideAdapter(getActivity(),sideItems);
getListView().setVerticalScrollBarEnabled(false);
setListAdapter(sideAdapter);
如果(savedInstanceState!=null){
sideAdapter.setSelectedItem(savedInstanceState.getInt(“sidePosition”);
sideAdapter.notifyDataSetChanged();
}
}
@凌驾
SaveInstanceState上的公共无效(束超出状态){
super.onSaveInstanceState(超出状态);
putInt(“sidePosition”,sideAdapter.getSelectedItem());
}
@凌驾
public void onListItemClick(列表视图lv、视图v、整数位置、长id){
if(sideAdapter.getSelectedItem()!=位置){
侧适配器。设置选择项(位置);
sideAdapter.notifyDataSetChanged();
}
开关(位置){
…根据位置切换碎片。
}
}
//切换上述片段的肉
私有void开关片段(片段片段,字符串标题){
如果(getActivity()==null)
返回;
如果(getActivity()实例为HomeActivity){
HomeActivity a=(HomeActivity)getActivity();
a、 内容(片段、标题);
}
}
}

首先,在活动布局中添加xml片段。 在活动onCreate中

getFragmentManager().findFragmentById(R.id.youtfragmentid).setRetainInstance(true)
这意味着不会在“重新创建”活动中重新创建片段

不要在onActivityCreated中更改ListView,因为它将在每次方向更改时重新生成。如果您设置了一个新的适配器,子适配器的状态将被重置

添加对已创建视图的null或布尔标志的检查。 下次调用onActivityCreated时,列表适配器不应更改

if (sideAdapter == null) {

    sideAdapter = new SideAdapter(getActivity(), sideItems);
        getListView().setVerticalScrollBarEnabled(false);
        setListAdapter(sideAdapter);

}
另外,不要在onCreateView中创建新视图,而是使用以前创建的视图

private View v;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    if (v == null) {
        v = inflater.inflate(R.layout.list, null);
    } else {
        // detatch from container and return the same view
        ((ViewGroup) getListView().getParent()).removeAllViews();
    }
    return v;
}

当前正在尝试其中一些更改,将很快报告。在添加setRetainInstance(true)并添加适配器null检查后,现在一切都很顺利。我也没有更改onCreateView。onCreateView是一个不相关(但推荐)的优化。您真的,真的想避免保留具有视图的片段。如果您的片段实例保留对其任何视图的任何引用或对
上下文的其他访问,您将泄漏整个
上下文,这非常糟糕。您可以使用
adb shell dumpsys meminfo
@romanurik查看内存中有多少上下文:如果我们不保留在新实例上调用的
onCreateView()
之前的“对其任何视图的引用”,只要我们不以任何其他方式保留
Context
自己,保留带有
视图的片段应该是安全的(否则表示框架中存在bug)。不推荐使用
onRetainNonConfigurationInstance()
时,允许保留片段是很重要的,试图迫使开发人员为此使用无视图片段可能会失败。我建议添加Lint规则,以帮助确保开发人员安全地使用保留的片段。