在应用 exit/orientation 更改时保存 ListView 项目
Saving ListView Items upon application exit/orientation change
我有一个简单的待办事项列表,我试图在应用程序退出和方向更改时保存待办事项(列表项)。我已经尝试了一些代码,但它似乎没有保存任何东西。这是我的 MainActivity。
package com.example.android.todolist;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity
{
//Variables
Button addTodo;
ListView listView;
EditText itemInput;
ArrayAdapter<String> adapter;
TextView myTodoList;
String stringInput;
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Add custom font to title
myTodoList = (TextView)findViewById(R.id.tvMyTodoList);
Typeface textViewFont = Typeface.createFromAsset(getAssets(),"High Tide - Demo.ttf");
myTodoList.setTypeface(textViewFont);
//Find views by ID
listView = (ListView) findViewById(R.id.lvTodoView);
itemInput = (EditText) findViewById(R.id.etAddItem);
addTodo = (Button) findViewById(R.id.btnAddTodo);
//Set adapter onto ListView
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>());
listView.setAdapter(adapter);
//On long click action
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.remove(adapter.getItem(position));
adapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, "Item Deleted", Toast.LENGTH_LONG).show();
return true;
}
});
//Add strikethrough to on click action, and remove strikethrough when clicked again
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
TextView addStrikethroughToListItem = (TextView) view;
if ((addStrikethroughToListItem.getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) == 0)
{
addStrikethroughToListItem.setPaintFlags(addStrikethroughToListItem.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
else
{
addStrikethroughToListItem.setPaintFlags(0);
}
}
});
}
//Method to add item to ListView
public void addItemToList(View view)
{
Context appContext = getApplicationContext();
String emptyItem = "Please enter an item";
int duration = Toast.LENGTH_LONG;
if (itemInput.length() > 1)
{
adapter.add(itemInput.getText().toString().trim());
adapter.notifyDataSetChanged();
itemInput.setText(" ");
}
else
{
Toast.makeText(appContext, emptyItem, duration).show();
}
}
private static int ix = 0;
@Override
protected void onPause()
{
super.onPause();
submitPrefs();
Log.e(TAG,"OnPause executed");
}
@Override
protected void onResume()
{
super.onResume();
getStoredPrefs();
Log.e(TAG,"onResume executed");
}
private void submitPrefs()
{
SharedPreferences pref = getBaseContext().getSharedPreferences("MyPrefsX",MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("InputX","My Iteration" + ix);
editor.commit();
ix++;
}
private void getStoredPrefs()
{
SharedPreferences pref = getBaseContext().getSharedPreferences("MyPrefsX",MODE_PRIVATE);
String s = pref.getString("InputX", "Not set yet");
Log.e(TAG,"My State == " + s);
}
}
我还没有向 onBackPressed 方法添加任何代码,因为我还没有做到这一点。现在我对 onSaveInstanceState 方法和 onRestoreInstanceState 方法很感兴趣。
这是我的XML。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.todolist.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp"
android:background="@drawable/sample_background3">
<TextView
android:id="@+id/tvMyTodoList"
android:layout_width="0dp"
android:layout_height="58dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="@string/my_todo_s"
android:textSize="40sp"
app:layout_constraintHorizontal_bias="0.512"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<EditText
android:hint="@string/enter_todo_here"
android:id="@+id/etAddItem"
android:layout_height="49dp"
android:layout_width="261dp"
android:labelFor="@+id/etAddItem"
android:inputType="textCapCharacters"
android:layout_marginStart="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/lvTodoView"/>
<Button
android:id="@+id/btnAddTodo"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:onClick="addItemToList"
android:text="@string/button"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/etAddItem"
app:layout_constraintRight_toRightOf="@+id/lvTodoView"
app:layout_constraintTop_toBottomOf="@+id/lvTodoView"/>
<ListView
android:id="@+id/lvTodoView"
android:layout_width="0dp"
android:layout_height="373dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.511"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/tvMyTodoList"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"/>
</android.support.constraint.ConstraintLayout>
对我做错了什么有什么想法吗?该应用程序未保存任何内容。唯一一次我发现我的待办事项仍在列表中是当我按下主页按钮并重新打开应用程序时。如果我以任何其他方式关闭应用程序,则不会保存任何内容。
我尝试过使用 SharedPreferences,但没有成功。我在论坛上询问 SharedPreferences 是否适合此操作,我被告知可以。我还询问了一个 SQLite 数据库,我被告知在这种情况下不需要它。我还在 YouTube 上尝试了各种教程,但没有任何效果。上面显示的代码是我尝试过的最后一种方法。我似乎找不到其他可以尝试的东西。
此外,由于这是我的第一个应用程序,如果有人能就我所做的工作给我一些一般性的反馈,无论是结构、代码还是任何人希望的任何建议,我将不胜感激摆脱我可能表现出的任何不良做法。
主页按钮已按下
从主页按钮关闭重新打开应用程序
按下后退按钮
您的问题不是无法将数据保存到 SharedPreference。问题是您想保留列表数据。抱歉,我第一次没听清楚。
我假设你是什么用户能够关闭应用程序,当用户重新打开应用程序时,待办事项列表会填充上次会话的数据。
A ListView
不会将一个会话的数据保存到下一个会话。你必须自己做。您的代码需要做大量的工作才能做到这一点。确实没有简单的解决方法。
最简单的方法是创建一个 csv 文件(或者可能是 JSON 字符串)来保存列表条目。每次调用 onPause
时保存它,然后检索列表 onResume
并重新填充列表。这有点脆弱,因为它依赖于设备文件系统。
另一种方法是集成 Android 的 SQLite 功能。这无疑是最优雅、最健壮和最灵活的方式。在 SQLite DB onPause
的列表中保存你想要的数据并检索它 onResume
.
你想怎么做真的是你的决定。一旦找到最适合您需求的解决方案并且您 运行 遇到代码问题,只需 post 一个新问题。
附加信息:
我有一个类似的应用程序。用户创建一个列表。在他们决定从中删除项目之前,此列表应保持原样。
由于我的列表显示了很多详细信息,个别元素可以更改解决方案是:
- 我在 JSON 结构化文件中维护列表数据。并将该文件保存在设备上。
- 每次用户添加或删除项目或更改列表中项目的数据时,我都会对 JSONObject
进行更改并将其保存到文件中。
- 当用户重新打开应用程序时(可能几天或几秒钟后),数据在文件的 JSON 结构化字符串中可用。
- 我解析此文件并使用自定义适配器将项目添加到我的列表中。
如果您的待办事项列表仅包含每个列表条目的简单单个条目字符串,那么您可能可以使用一个简单的 csv 文件。当 activity 启动时,您将打开该文件。对文件的内容执行拆分,这将为您提供一个字符串数组。您可以使用这个字符串数组来填充您的列表。
我有一个简单的待办事项列表,我试图在应用程序退出和方向更改时保存待办事项(列表项)。我已经尝试了一些代码,但它似乎没有保存任何东西。这是我的 MainActivity。
package com.example.android.todolist;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity
{
//Variables
Button addTodo;
ListView listView;
EditText itemInput;
ArrayAdapter<String> adapter;
TextView myTodoList;
String stringInput;
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Add custom font to title
myTodoList = (TextView)findViewById(R.id.tvMyTodoList);
Typeface textViewFont = Typeface.createFromAsset(getAssets(),"High Tide - Demo.ttf");
myTodoList.setTypeface(textViewFont);
//Find views by ID
listView = (ListView) findViewById(R.id.lvTodoView);
itemInput = (EditText) findViewById(R.id.etAddItem);
addTodo = (Button) findViewById(R.id.btnAddTodo);
//Set adapter onto ListView
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>());
listView.setAdapter(adapter);
//On long click action
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.remove(adapter.getItem(position));
adapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, "Item Deleted", Toast.LENGTH_LONG).show();
return true;
}
});
//Add strikethrough to on click action, and remove strikethrough when clicked again
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
TextView addStrikethroughToListItem = (TextView) view;
if ((addStrikethroughToListItem.getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) == 0)
{
addStrikethroughToListItem.setPaintFlags(addStrikethroughToListItem.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
else
{
addStrikethroughToListItem.setPaintFlags(0);
}
}
});
}
//Method to add item to ListView
public void addItemToList(View view)
{
Context appContext = getApplicationContext();
String emptyItem = "Please enter an item";
int duration = Toast.LENGTH_LONG;
if (itemInput.length() > 1)
{
adapter.add(itemInput.getText().toString().trim());
adapter.notifyDataSetChanged();
itemInput.setText(" ");
}
else
{
Toast.makeText(appContext, emptyItem, duration).show();
}
}
private static int ix = 0;
@Override
protected void onPause()
{
super.onPause();
submitPrefs();
Log.e(TAG,"OnPause executed");
}
@Override
protected void onResume()
{
super.onResume();
getStoredPrefs();
Log.e(TAG,"onResume executed");
}
private void submitPrefs()
{
SharedPreferences pref = getBaseContext().getSharedPreferences("MyPrefsX",MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("InputX","My Iteration" + ix);
editor.commit();
ix++;
}
private void getStoredPrefs()
{
SharedPreferences pref = getBaseContext().getSharedPreferences("MyPrefsX",MODE_PRIVATE);
String s = pref.getString("InputX", "Not set yet");
Log.e(TAG,"My State == " + s);
}
}
我还没有向 onBackPressed 方法添加任何代码,因为我还没有做到这一点。现在我对 onSaveInstanceState 方法和 onRestoreInstanceState 方法很感兴趣。
这是我的XML。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.todolist.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp"
android:background="@drawable/sample_background3">
<TextView
android:id="@+id/tvMyTodoList"
android:layout_width="0dp"
android:layout_height="58dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="@string/my_todo_s"
android:textSize="40sp"
app:layout_constraintHorizontal_bias="0.512"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<EditText
android:hint="@string/enter_todo_here"
android:id="@+id/etAddItem"
android:layout_height="49dp"
android:layout_width="261dp"
android:labelFor="@+id/etAddItem"
android:inputType="textCapCharacters"
android:layout_marginStart="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/lvTodoView"/>
<Button
android:id="@+id/btnAddTodo"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:onClick="addItemToList"
android:text="@string/button"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/etAddItem"
app:layout_constraintRight_toRightOf="@+id/lvTodoView"
app:layout_constraintTop_toBottomOf="@+id/lvTodoView"/>
<ListView
android:id="@+id/lvTodoView"
android:layout_width="0dp"
android:layout_height="373dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.511"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/tvMyTodoList"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"/>
</android.support.constraint.ConstraintLayout>
对我做错了什么有什么想法吗?该应用程序未保存任何内容。唯一一次我发现我的待办事项仍在列表中是当我按下主页按钮并重新打开应用程序时。如果我以任何其他方式关闭应用程序,则不会保存任何内容。
我尝试过使用 SharedPreferences,但没有成功。我在论坛上询问 SharedPreferences 是否适合此操作,我被告知可以。我还询问了一个 SQLite 数据库,我被告知在这种情况下不需要它。我还在 YouTube 上尝试了各种教程,但没有任何效果。上面显示的代码是我尝试过的最后一种方法。我似乎找不到其他可以尝试的东西。
此外,由于这是我的第一个应用程序,如果有人能就我所做的工作给我一些一般性的反馈,无论是结构、代码还是任何人希望的任何建议,我将不胜感激摆脱我可能表现出的任何不良做法。
主页按钮已按下
从主页按钮关闭重新打开应用程序
按下后退按钮
您的问题不是无法将数据保存到 SharedPreference。问题是您想保留列表数据。抱歉,我第一次没听清楚。
我假设你是什么用户能够关闭应用程序,当用户重新打开应用程序时,待办事项列表会填充上次会话的数据。
A ListView
不会将一个会话的数据保存到下一个会话。你必须自己做。您的代码需要做大量的工作才能做到这一点。确实没有简单的解决方法。
最简单的方法是创建一个 csv 文件(或者可能是 JSON 字符串)来保存列表条目。每次调用 onPause
时保存它,然后检索列表 onResume
并重新填充列表。这有点脆弱,因为它依赖于设备文件系统。
另一种方法是集成 Android 的 SQLite 功能。这无疑是最优雅、最健壮和最灵活的方式。在 SQLite DB onPause
的列表中保存你想要的数据并检索它 onResume
.
你想怎么做真的是你的决定。一旦找到最适合您需求的解决方案并且您 运行 遇到代码问题,只需 post 一个新问题。
附加信息:
我有一个类似的应用程序。用户创建一个列表。在他们决定从中删除项目之前,此列表应保持原样。
由于我的列表显示了很多详细信息,个别元素可以更改解决方案是:
- 我在 JSON 结构化文件中维护列表数据。并将该文件保存在设备上。
- 每次用户添加或删除项目或更改列表中项目的数据时,我都会对 JSONObject
进行更改并将其保存到文件中。
- 当用户重新打开应用程序时(可能几天或几秒钟后),数据在文件的 JSON 结构化字符串中可用。
- 我解析此文件并使用自定义适配器将项目添加到我的列表中。
如果您的待办事项列表仅包含每个列表条目的简单单个条目字符串,那么您可能可以使用一个简单的 csv 文件。当 activity 启动时,您将打开该文件。对文件的内容执行拆分,这将为您提供一个字符串数组。您可以使用这个字符串数组来填充您的列表。