如何保存列表视图项目/适配器片段和恢复从回堆栈



我一直试图搜索这个问题,但我无法得到任何解决方案。我有一个关于保存ListView项目片段的问题。情况是我有几个片段

假设片段A,片段B和片段C,片段A有A当用户滚动列表视图时,列表视图的项目可以被改变(就像社交媒体应用中的时间轴一样)。当我改变片段时A,我使用了addToBackStack(null)方法。

问题是,如何保存列表视图和恢复其如果后退按钮被按下?

onSaveInstanceState()永远不会被调用,因为Activity主机永远不会被杀死,只使用this改变片段:

public void changeFragment(Fragment fragment, ColorDrawable colorDrawable){
    Fragment newFrag = fragment;
    ColorDrawable newColor = colorDrawable;
    String backStateName = fragment.getClass().getName();
    FragmentManager manager = getSupportFragmentManager();
    boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
    if (!fragmentPopped){ //fragment not in back stack, create it.
        FragmentTransaction ft = manager.beginTransaction();
        ft.replace(R.id.content_fragment, fragment);
        ft.addToBackStack(backStateName);
        ft.commit();
    }
    //to change the actionbar color
    getSupportActionBar().setBackgroundDrawable(newColor);
}

下面是我试图保存和恢复listview的代码:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //try to save listview scroll
        index = myList.getFirstVisiblePosition();
        View v = myList.getChildAt(0);
        top = (v == null) ? 0 : (v.getTop() - myList.getPaddingTop());
        index = 1;
        //try to save listview items
        savedAdapter = adapter;
        fromBackStack = true;
    }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        myList.setSelectionFromTop(index, top);
        myList.setAdapter(savedAdapter);
    }

这里是我目前所做的代码:

    package com.ngapainya.ngapainya.fragment;

import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.net.ParseException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import com.ngapainya.ngapainya.R;
import com.ngapainya.ngapainya.activity.volunteer.ContainerActivity;
import com.ngapainya.ngapainya.adapter.HomeAdapter;
import com.ngapainya.ngapainya.fragment.child.DetailPostFragment;
import com.ngapainya.ngapainya.model.Home;
import java.util.ArrayList;
/**
 * A simple {@link Fragment} subclass.
 */
public class HomeFragment extends Fragment implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener{
    private FragmentActivity myContext;
    private View myFragmentView;
    private ArrayList<Home> filelist;
    private ListView myList;
    private HomeAdapter adapter;
    private SwipeRefreshLayout swipeRefreshLayout;
    //try save instance listview
    boolean fromBackStack = false;
    int index;
    int top;
    HomeAdapter savedAdapter;
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //try to save listview scroll
        index = myList.getFirstVisiblePosition();
        View v = myList.getChildAt(0);
        top = (v == null) ? 0 : (v.getTop() - myList.getPaddingTop());
        index = 1;
        //try to save listview items
        savedAdapter = adapter;
        fromBackStack = true;
    }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        myList.setSelectionFromTop(index, top);
        myList.setAdapter(savedAdapter);
    }
    @Override
    public void onAttach(Activity activity) {
        myContext = (FragmentActivity) activity;
        super.onAttach(activity);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        myFragmentView = inflater.inflate(R.layout.fragment_home, container, false);
        filelist = new ArrayList<Home>();
        //dummy data
        filelist.add(new Home("post", 1)); //post image
        filelist.add(new Home("post", 2)); //post location
        filelist.add(new Home("post", 3)); //post url
        filelist.add(new Home("post", 4)); //become friend with
        filelist.add(new Home("post", 0)); //post status
        swipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);
        /**
         * Showing Swipe Refresh animation on activity create
         * As animation won't start on onCreate, post runnable is used
         */
        swipeRefreshLayout.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        swipeRefreshLayout.setRefreshing(true);
                                        //do something
                                        swipeRefreshLayout.setRefreshing(false);
                                    }
                                }
        );
        myList = (ListView) myFragmentView.findViewById(R.id.list_home);
        //myList.setAdapter(new HomeAdapter(myContext, filelist));
        adapter = new HomeAdapter(myContext, filelist);
        myList.setOnItemClickListener(this);
        if(!fromBackStack) {
            new RemoteDataTask().execute();
        }
        return myFragmentView;
    }
    /**
     * This method is called when swipe refresh is pulled down
     */
    @Override
    public void onRefresh() {
        //do something
        myList.setAdapter(adapter);
        ArrayList<Home> new_filelist = new ArrayList<>();
        new_filelist.add(new Home("Post", 4));
        filelist.addAll(0, new_filelist);
        adapter.notifyDataSetChanged();
        swipeRefreshLayout.setRefreshing(false);
    }
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Home tmp = (Home) parent.getItemAtPosition(position);
        DetailPostFragment detailPostFragment = new DetailPostFragment();
        Bundle args = new Bundle();
        switch (tmp.type) {
            case 0:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 1:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 2:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 3:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 4:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
        }
    }
    private class RemoteDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override
        protected ArrayList<Home> doInBackground(String... urls) {
            try {
                ArrayList<Home> new_filelist = new ArrayList<Home>();
                new_filelist.add(new Home("post", 3)); //post url
                new_filelist.add(new Home("post", 4)); //become friend with
                new_filelist.add(new Home("post", 0)); //post status
                filelist.addAll(new_filelist);
            } catch (ParseException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return filelist;
        }
        @Override
        protected void onPostExecute(ArrayList<Home> organization) {
            myList.setAdapter(new HomeAdapter(myContext, filelist));
            // Create an OnScrollListener
            myList.setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view,
                                                 int scrollState) { // TODO Auto-generated method stub
                    int threshold = 1;
                    int count = myList.getCount();
                    if (scrollState == SCROLL_STATE_IDLE) {
                        if (myList.getLastVisiblePosition() >= count
                                - threshold) {
                            // Execute LoadMoreDataTask AsyncTask
                            new LoadMoreDataTask().execute();
                        }
                    }
                }
                @Override
                public void onScroll(AbsListView view, int firstVisibleItem,
                                     int visibleItemCount, int totalItemCount) {
                    // TODO Auto-generated method stub
                }
            });
        }
    }
    public class LoadMoreDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override
        protected ArrayList<Home> doInBackground(String... urls) {
            try {
                // web service request
                ArrayList<Home> new_filelist = new ArrayList<Home>();
                new_filelist.add(new Home("post", 0)); //post status
                if(new_filelist  != null && new_filelist.size() > 0 ){
                    filelist.addAll(new_filelist);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return filelist;
        }
        @Override
        protected void onPostExecute(ArrayList<Home> organization) {
            int position = myList.getLastVisiblePosition();
            adapter = new HomeAdapter(myContext, filelist);
            myList.setAdapter(adapter);
            adapter.notifyDataSetChanged();
            myList.setSelectionFromTop(position, 0);
        }
    }
}

我希望有人能帮助我,谢谢。

更新代码这是我的代码到目前为止,它的工作,当我试图保存listview项目和它的适配器,也许这是有点棘手。如果有人有什么建议,我将不胜感激。

package com.ngapainya.ngapainya.fragment;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.net.ParseException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import com.ngapainya.ngapainya.R;
import com.ngapainya.ngapainya.activity.volunteer.ContainerActivity;
import com.ngapainya.ngapainya.adapter.HomeAdapter;
import com.ngapainya.ngapainya.fragment.child.DetailPostFragment;
import com.ngapainya.ngapainya.model.Home;
import java.util.ArrayList;
/**
 * A simple {@link Fragment} subclass.
 */
public class HomeFragment extends Fragment implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener{
    private FragmentActivity myContext;
    private View myFragmentView;
    private ArrayList<Home> filelist;
    private ListView myList;
    private HomeAdapter adapter;
    private SwipeRefreshLayout swipeRefreshLayout;
    /*
    * these variables used to restore the listview
    * when calling the fragment from backstack
    * */
    private boolean fromBackStack = false;
    private HomeAdapter savedAdapter;
    private ArrayList<Home> savedFilelist;
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        savedAdapter = adapter;
        savedFilelist = filelist;
        fromBackStack = true;
        Log.e("onDestroyView", "onDestroyView");
    }
    @Override
    public void onAttach(Activity activity) {
        myContext = (FragmentActivity) activity;
        super.onAttach(activity);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        myFragmentView = inflater.inflate(R.layout.fragment_home, container, false);
        Log.e("onCreateView", "onCreateView");
        swipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);
        /**
         * Showing Swipe Refresh animation on activity create
         * As animation won't start on onCreate, post runnable is used
         */
        /*swipeRefreshLayout.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        swipeRefreshLayout.setRefreshing(true);
                                        //do something
                                        swipeRefreshLayout.setRefreshing(false);
                                    }
                                }
        );*/
        myList = (ListView) myFragmentView.findViewById(R.id.list_home);
        //myList.setAdapter(new HomeAdapter(myContext, filelist));
        myList.setOnItemClickListener(this);
        filelist = new ArrayList<Home>();
        adapter = new HomeAdapter(myContext, filelist);
        if(fromBackStack) {
            filelist = savedFilelist;
            adapter = savedAdapter;
        }
        new RemoteDataTask().execute();
        return myFragmentView;
    }
    /**
     * This method is called when swipe refresh is pulled down
     */
    @Override
    public void onRefresh() {
        ArrayList<Home> new_filelist = new ArrayList<>();
        new_filelist.add(new Home("Post", 4));
        filelist.addAll(0, new_filelist);
        adapter.notifyDataSetChanged();
        swipeRefreshLayout.setRefreshing(false);
        Log.e("onRefresh", "onRefresh");
    }
    /*
    * This method is called whenever the listview item is clicked
    * */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Home tmp = (Home) parent.getItemAtPosition(position);
        DetailPostFragment detailPostFragment = new DetailPostFragment();
        Bundle args = new Bundle();
        switch (tmp.type) {
            case 0:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 1:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 2:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 3:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
            case 4:
                args.putInt("postType", tmp.type);
                detailPostFragment.setArguments(args);
                ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                break;
        }
    }
    /*
    * This method is called in onCreateView method
    * Used to load data from server and populate them into
    * the listview
    * */
    private class RemoteDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override
        protected ArrayList<Home> doInBackground(String... urls) {
            try {
                ArrayList<Home> new_filelist = new ArrayList<Home>();
                //dummy data
                new_filelist.add(new Home("post", 1)); //post image
                new_filelist.add(new Home("post", 2)); //post location
                new_filelist.add(new Home("post", 3)); //post url
                new_filelist.add(new Home("post", 4)); //become friend with
                new_filelist.add(new Home("post", 0)); //post status
                new_filelist.add(new Home("post", 3)); //post url
                new_filelist.add(new Home("post", 4)); //become friend with
                new_filelist.add(new Home("post", 0)); //post status
                filelist.addAll(new_filelist);
            } catch (ParseException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return filelist;
        }
        @Override
        protected void onPostExecute(ArrayList<Home> organization) {
            myList.setAdapter(adapter);
            // Create an OnScrollListener
            myList.setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view,
                                                 int scrollState) { // TODO Auto-generated method stub
                    int threshold = 1;
                    int count = myList.getCount();
                    if (scrollState == SCROLL_STATE_IDLE) {
                        if (myList.getLastVisiblePosition() >= count
                                - threshold) {
                            // Execute LoadMoreDataTask AsyncTask
                            new LoadMoreDataTask().execute();
                        }
                    }
                }
                @Override
                public void onScroll(AbsListView view, int firstVisibleItem,
                                     int visibleItemCount, int totalItemCount) {
                    // TODO Auto-generated method stub
                }
            });
        }
    }
    /*
    * This method is called when the listview pulled down
    * it will trigger this method to load more items from server
    * */
    public class LoadMoreDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override
        protected ArrayList<Home> doInBackground(String... urls) {
            try {
                // web service request
                ArrayList<Home> new_filelist = new ArrayList<Home>();
                new_filelist.add(new Home("post", 0)); //post status
                new_filelist.add(new Home("post", 1));
                if(new_filelist  != null && new_filelist.size() > 0 ){
                    filelist.addAll(new_filelist);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return filelist;
        }
        @Override
        protected void onPostExecute(ArrayList<Home> organization) {
            int position = myList.getLastVisiblePosition();
            //adapter = new HomeAdapter(myContext, filelist);
            myList.setAdapter(adapter);
            adapter.notifyDataSetChanged();
            myList.setSelectionFromTop(position, 0);
        }
    }
}

我终于明白了…我不知道这是否是最好的解决方案,但到目前为止,它对我来说是有效的。我只需要一个方法和几个变量,就像这样。

@Override
public void onDestroyView() {
    super.onDestroyView();
    savedAdapter = adapter;
    savedFilelist = filelist;
    fromBackStack = true;
    Log.e("onDestroyView", "onDestroyView");
}

谢谢。

最新更新