使用共享首选项保存和重新加载 ListView [保存 onDestroy()]

Posted

技术标签:

【中文标题】使用共享首选项保存和重新加载 ListView [保存 onDestroy()]【英文标题】:Saving and Reloading ListView using Shared Preferences [Saving onDestroy()] 【发布时间】:2013-09-13 05:49:15 【问题描述】:

我正在创建一个待办事项列表。现在我的应用程序在 ListView 中添加和删除数据。但是,当我关闭我的应用程序时,数据会被删除。我想使用 SharedPreferences 来保存数据 onDestroy(),然后当我的应用程序打开时,我希望重新加载数据。

但是,我不知道如何完成这项任务。 谁能帮助我使用共享首选项保存 ListView(我正在寻找代码)?

只有一个共享偏好的教程我希望在我的应用程序关闭时动态添加多个字符串。然后当我重新打开它时,数据就会出现。我只使用一个活动页面,一切都会发生在一页上。

这是我的代码:

public class Main_ToDoList extends Activity implements OnClickListener

private Button btnAdd;
private EditText et;
private ListView lv;
ArrayList<String> list = new ArrayList<String>();
ArrayAdapter<String> adapter;
final Context context = this;

@Override
protected void onCreate(Bundle savedInstanceState)

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    btnAdd = (Button)findViewById(R.id.addTaskBtn);
    btnAdd.setOnClickListener(this);
    et = (EditText)findViewById(R.id.editText);
    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, list);

    // set the lv variable to your list in the xml
    lv=(ListView)findViewById(R.id.list);
    lv.setAdapter(adapter);

    // set ListView item listener
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
    
        @Override
        public void onItemClick(AdapterView<?> parent, View view, final int position, long id)
        
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
            alertDialogBuilder.setTitle("Confirm Delete");
            alertDialogBuilder.setMessage("Sure you want to delete?");
            alertDialogBuilder.setCancelable(false);
            alertDialogBuilder.setPositiveButton("Yes", new DialogInterface.OnClickListener()
            
                @Override
                public void onClick(DialogInterface dialogInterface, int i)
                
                    adapter.remove(adapter.getItem(position));
                
            );
            alertDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener()
            
                @Override
                public void onClick(DialogInterface dialogInterface, int i)
                
                    dialogInterface.cancel();
                
            );
            AlertDialog alertDialog = alertDialogBuilder.create();
            alertDialog.show();
        
    );

public void onClick(View v)

    String input = et.getText().toString();
    if(input.length() > 0)
    
        adapter.add(input);
        et.setText("");
    

@Override
public void onDestroy()

    super.onDestroy();

@Override
public boolean onCreateOptionsMenu(Menu menu)

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main__to_do_list, menu);
    return true;

 

【问题讨论】:

为什么不用数据库? 【参考方案1】:

作为suggested by Stefano Munarini,你可以使用数据库。

另一方面,您可以循环 ArrayAdapter 的元素(包装您的 ArrayList)并将它们存储到您的 SharedPreferences 中,如下所示:

public static final String PREFERENCES_TODO = "TODO_List_Shared_Preferences";
// ...
SharedPreferences prefs = context.getSharedPreferences(PREFERENCES_TODO,
                                                       MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
// This will remove all entries of the specific SharedPreferences
editor.clear();
for (int i = 0; i < adapter.getCount(); ++i)
    // This assumes you only have the list items in the SharedPreferences.
    editor.putString(String.valueOf(i), adapter.getItem(i));

editor.commit();
// ...
// And the reverse process:
SharedPreferences prefs = context.getSharedPreferences(PREFERENCES_TODO,
                                                       MODE_PRIVATE);
for (int i = 0;; ++i)
    final String str = prefs.getString(Integer.valueOf(i), "");
    if (!str.equals(""))
        adapter.add(str);
     else 
        break; // Empty String means the default value was returned.
    

一些注意事项:

将 SharedPreferences 保存在 onPause() 而不是 onDestroy() 中,这不能保证被调用。参考Activity Lifecycle。 禁止用户输入空字符串。 (编辑:你已经在这样做了。) 如果您知道不会有 2 个相同的字符串(禁止或其他方式),您可以使用 SharedPreferences.Editor.putStringSet(String, Set&lt;String&gt;) 来使用单个条目。 如果有很多元素,或者如果您计划添加额外选项(即截止日期、类别等),您应该真正考虑数据库选项,因为 SharedPreferences 解决方案不能提供良好的可扩展性。李>

【讨论】:

这是在回答你的问题吗?【参考方案2】:

Android SharedPreferences 用于存储单个键值对数据。换句话说,它不是用来存储重复和复杂的数据。在您的情况下,列表视图可能包含超过 100 行或更多行,具体取决于您的应用程序。如果您要为每一行创建一个 SharedPreferences 对象,它将是 100+,这根本没有效率。解决方法如前所述,使用 Android 的 SQLite 数据库。

一个不错的教程:http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/

【讨论】:

【参考方案3】:

我知道它很旧,但我想为那些仍然想使用 sharepref 并看到这篇文章的人分享我的解决方案。

1) 创建扩展 ArrayAdapter 的自定义类并覆盖 toString 方法。只需在每行之间附加并放置 ','。

public class GroceryArrayAdapter extends ArrayAdapter<String> 
    public GroceryArrayAdapter(Context context, int resource) 
        super(context, resource);
    

    public GroceryArrayAdapter(Context context, int resource, int          textViewResourceId) 
        super(context, resource, textViewResourceId);
    

    public GroceryArrayAdapter(Context context, int resource, int     textViewResourceId, String[] objects) 
        super(context, resource, textViewResourceId, objects);
    

    public GroceryArrayAdapter(Context context, int resource, String[]     objects) 
        super(context, resource, objects);
    

    public GroceryArrayAdapter(Context context, int resource, List<String> objects) 
        super(context, resource, objects);
    

    public GroceryArrayAdapter(Context context, int resource, int     textViewResourceId, List<String> objects) 
        super(context, resource, textViewResourceId, objects);
    

    @Override
    public String toString()
        String data = "";
        for (int i = 0; i < getCount(); i++) 
            data += getItem(i).toString() ;
            if( i + 1 < getCount())
                data += ",";
            
        
        return  data;
    

2) 将数据保存为一个字符串。放入onPause()

    private void saveData()
        sharedPrefs = activity.getSharedPreferences(Constants.APPSharePref,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor e = sharedPrefs.edit();
        e.putString(Constants.GROCERY,**grocery_adapter.toString()**);
        e.commit();
    

3) 在 onResume 中,通过用 ',' 分割字符串来恢复数据并将其添加到适配器。

    private void loadDataFromPref()
        sharedPrefs = getActivity().getSharedPreferences(Constants.APPSharePref,
            Context.MODE_PRIVATE);

        String gList =sharedPrefs.getString(Constants.GROCERY,"");
        if(!"".equals(gList) && ""!=gList)
            String [] str = gList.split(",");
            for (String item : str) 
                grocery_adapter.add(item);
            
        
    

【讨论】:

以上是关于使用共享首选项保存和重新加载 ListView [保存 onDestroy()]的主要内容,如果未能解决你的问题,请参考以下文章

Android - 保存自定义对象 - 共享首选项或数据库?

保存的首选项在重新启动时不起作用

如何使用共享首选项让用户保持登录状态?

共享首选项保存和检索数据

如何使用 dart/flutter 中的共享首选项保存和获取列表列表

如何保存阵列?