How to save state of Fragment having listview

2020-07-03 05:09发布

Here is a situation. I want to navigate from Fragment A-> B-> C.

In B Fragment there is listview. On item click I open the detail view C Fragment. Ofcourse I used replace method and added addtoBackStack(null) while transactiong from B to C so that on Back press it returned to B.

All goes well. But when I return to B from C, the view is being refreshed and hence the webservice is being called again. I don't want to do this. I want to retain the B Fragment state with listview.

I got some post of Retain Instance, but it didn't help that much.

Any help is much appreciated.

Thanks.

4条回答
仙女界的扛把子
2楼-- · 2020-07-03 05:35

I think you can save your ListView's position just before you're leaving fragment B. Maybe do that in fragment B's onStop(). And when you go back, you can fetch that position and restore it to ListView, do that for example in fragment B's onStart(). The position data maybe saved at the Activity so it won't be lost even the fragment detached.

One thing should be noticed that(I've been trapped by this), if the saved position data is updated by the background service, you should avoid restoring it to ListView before the life-cycle stage onStart() of fragment B, because actually, the framework will save the view's state just before leaving the fragment and restore it when get back. So if you restore your position before the framework do that, the framework's restore data will override yours.

查看更多
放我归山
3楼-- · 2020-07-03 05:36

you can save define your ui in oncreate. when in onCreateView, only add it the layout. so the view state can save perfect.

this is my sv:

in oncreate

 LayoutInflater inflater = (LayoutInflater)
            ctx.getSystemService(ctx.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.pulltorefreshgridview, null);
    mPullRefreshGridView = (PullToRefreshGridView) view
            .findViewById(R.id.listcate_pullrefresh_gridview);

strong text in onCreateView

if (rootView != null) ((LinearLayout)rootView).removeAllViews();
View v = inflater.inflate(R.layout.listcate_fragment, container, false);
rootView = v;


    ((LinearLayout) v).addView(mPullRefreshGridView,
            new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.FILL_PARENT,
                    LinearLayout.LayoutParams.FILL_PARENT));
查看更多
▲ chillily
4楼-- · 2020-07-03 05:47

As explained here you can use onSaveInstanceState() to save data in the Bundle and retrieve that data in the onRestoreInstanceState() method.

Often setRetainState(true) is mentioned as way to keep the ui state in fragment, but it does not work for you because you are using the backstack.

So a good way for you could be to save the scrollposition in onSaveInstanceState() and restore it in onRestoreInstanceState() like this:

public class MyListFragment extends ListFragment {

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

     int index = this.getListView().getFirstVisiblePosition();
     View v = this.getListView().getChildAt(0);
     int top = (v == null) ? 0 : v.getTop();

     outState.putInt("index", index);
     outState.putInt("top", top);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    [...]
    if (savedInstanceState != null) {
        // Restore last state for checked position.
        index = savedInstanceState.getInt("index", -1);
        top = savedInstanceState.getInt("top", 0);
    }
    if(index!=-1){
     this.getListView().setSelectionFromTop(index, top);
  }

}

Further more you can find a more detailed similiar example here.

查看更多
我只想做你的唯一
5楼-- · 2020-07-03 05:56

I have solved this problem by creating my Adapter on onCreate() instead of onCreateView().

This is because (I think) the fragment that is added to the backstack lost its View and then it has to recreate the view. onCreateView() get called and incidentally recreate your adapter.

查看更多
登录 后发表回答