使用自定义列表适配器保存和恢复ListView

Osb*_*Cox 3 android listview android-listview android-fragments

我目前正在使用a custom list adapter并在运行时修改listview的行(更改文本,按钮等).

我想找到一种方法来保存/恢复listview在运行时创建的更改,当我启动另一个片段然后返回到包含listview的片段时.

目前,每次都会重新加载列表视图,并且所有运行时更改都将丢失.

以下显示了我如何设置列表适配器.

 public void setAdapterToListView(ArrayList<item> list) {
        ItemList = list;
        ItemAdapter adapter = new MenuItemAdapter(list, getActivity(), this);
        ItemListView.setAdapter(adapter);
    }
Run Code Online (Sandbox Code Playgroud)

然后我使用自定义列表适配器在运行时进行更改(如上所述).以下是我在运行时如何更改内容的片段:

if (holder.qty.getText().toString().equals("Qty")) {
    relativeLayout.setBackgroundColor(row.getResources().getColor(R.color.navDrawerL ightBlue));
    holder.qty.setText("1");
    holder.qty.startAnimation(anim);
    holder.removeItem.setBackgroundResource(R.drawable.remove_item_red);
    holder.removeItem.setEnabled(true);

   ...
Run Code Online (Sandbox Code Playgroud)

有没有推荐的方法来解决这个问题?

Jay*_*yer 6

适配器

您将希望自定义适配器为其内部数据实现某种getter.例如

public ArrayList<YourDataType> getList() {
    return new ArrayList<YourDataType>(mAdapterData);
}
Run Code Online (Sandbox Code Playgroud)

活动

然后在您的活动/片段中,您需要保存并恢复该数据.

private static final String STATE_LIST = "State Adapter Data"

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelableArrayList(STATE_LIST, getAdapter().getList());
}
Run Code Online (Sandbox Code Playgroud)

虽然有一种onRestoreInstanceState()方法可以覆盖,但我通常会在此期间恢复onCreate().通常在其他事物被实例化时更方便.要么可行,要么可行.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //If restoring from state, load the list from the bundle
    if (savedInstanceState != null) {
        ArrayList<YourDataType> list = savedInstanceState.getParcelableArrayList(STATE_LIST);
        ItemAdapter adapter = new MenuItemAdapter(list, getActivity(), this);
    } else {
          //Else we are creating our Activity from scratch, pull list from where ever you initially get it from
          ArrayList<YourDataType> list = getInitData();
          ItemAdapter adapter = new MenuItemAdapter(list, getActivity(), this);
    }
}
Run Code Online (Sandbox Code Playgroud)

YourDataType

你没有提到是什么YourDataType,但我认为它是一个自定义类.为了使用捆绑的savedstate,它必须实现Parcelable.Android的Parcelable 开发链接和StackOverFlow 帖子解释了如何使用Parcelable 编写自己的自定义类.

更新

根据您正在使用的片段,将决定是否onSavedInstanceState()将调用该方法.从问你的问题的方式来看,我假设你正在将一个片段推到backstack上以在另一个上面加载另一个片段.然后点击后退按钮将从后台重新加载该片段...并传递捆绑状态以从中重新加载.

当然,这只是众多场景中的一种.这个片段完全有可能只执行onPause()后跟onStop()...然后当重新显示片段时,只看到它onStart()后面跟着onResume().在这种情况下,没有保存状态,因为片段从未被完全销毁,因此没有任何东西可以恢复.它应该处于相同的状态.如果它不是,而是你看到它重新加载初始数据......那么你可能正在重新加载或之后的初始数据onStart().您需要将所有初始化数据移动到其他位置onCreate().

另一个可能的情况是你完全破坏片段而不将它放在后台上.重新初始化它不会有保存的状态.如果你想事先将这个片段"恢复"回状态,那么你就不能依赖它onSavedInstanceState().您需要手动将这些信息手动保存在内存,磁盘或数据库中.然后从中拉出来.

遗憾的是,带有片段的生命周期非常复杂,并且极大地依赖于使用,甚至在支持库与本机片段之间.


Osb*_*Cox 0

经过一些阅读/研究后,我最终通过使用 Gson ( https://code.google.com/p/google-gson/ ) 将适配器数据保存到“已保存的首选项”来解决这个问题。

我使用 Gson 首先将对象数组转换为 Json,然后将 Json 字符串存储在“已保存的首选项”中。

随后,我能够根据需要检索这些并再次将 Json 读入 Java 对象,将它们存储在数组列表中并将其传递给我的 listview 适配器。

以下是该过程的简要概述,供任何想要做类似事情的人参考。

保存到共享首选项:

    SharedPreferences settings;
    Editor editor;
    settings = c.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
    editor = settings.edit();
    Gson gson = new Gson();
    String ItemsJson = gson.toJson(list);
    editor.putString(categoryId, ItemsJson);
    editor.apply();
Run Code Online (Sandbox Code Playgroud)

从共享偏好中读取:

    if (settings.contains(categoryId) {
       String jsonItems = settings.getString(categoryId, null);
       Gson gson = new Gson();
       Item[] favoriteItems = gson.fromJson(jsonItems, Item[].class);
       list = Arrays.asList(favoriteItems);
       ItemsFromSharedPrefs = new ArrayList<>(list);
       AllCategories.addAll(ItemsFromSharedPrefs);
   } etc...
Run Code Online (Sandbox Code Playgroud)