在应用程序退出/方向更改时保存ListView项目

时间:2017-10-05 20:01:26

标签: java android listview android-studio-2.3 saving-data

我有一个简单的待办事项列表,其中我试图在应用程序退出时和方向更改时保存Todo(列表项)。我尝试了一些代码,它似乎没有保存任何东西。这是我的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>

关于我做错了什么的任何想法?该应用程序不能保存任何内容。我发现我的Todo仍然在列表中的唯一一次是当我按下主页按钮并重新打开应用程序时。如果我以任何其他方式关闭应用程序,则不会保存任何内容。

我尝试过使用SharedPreferences,但我没有运气。我在论坛上问过SharedPreferences是否适合这个动作,我被告知它没问题。我还询问了一个SQLite数据库,我被告知在这种情况下不需要它。我也在YouTube上尝试了各种教程,但没有任何工作。上面显示的代码是我尝试过的最后一种方法。我似乎无法找到其他任何可以尝试的东西。

此外,由于这是我的第一个应用程序,如果有人可以就我在结构,代码或任何建议方面所做的事情给我一些一般性反馈,我将非常感激。任何人都希望摆脱我可能已经表现出的任何不良行为。

按下主页按钮 Home Button Pressed

从主页按钮关闭重新打开应用程序

Re-Open app from Home Button Close

后退按钮按

Back Button Pressed

1 个答案:

答案 0 :(得分:0)

您的问题不在于您无法将数据保存到SharedPreference。问题是你想要保留列表数据。对不起,我第一次没有抓到它。

我假设用户可以关闭应用程序,当用户重新打开应用程序时,todo列表会填充上一个会话中的数据。

ListView不会将一个会话的数据保留到下一个会话。你必须自己做。您的代码需要相当多的工作才能完成。真的没有简单的解决方法。

最简单的可能性是创建一个csv文件(或者可能是一个JSON字符串)来保存列表条目。每次调用onPause时保存它,然后检索列表onResume并重新填充列表。这有点脆弱,因为它依赖于设备文件系统。

另一种方法是集成Android的SQLite功能。这当然是最优雅,最强大和最灵活的方式。将您想要的数据保存在SQLite数据库onPause的列表中,并将其检索到onResume

你想怎么做才是你的决定。一旦找到最符合您需求的解决方案,并且您的代码遇到问题,只需发布​​一个新问题。

其他信息:

我有一个类似的应用程序。用户创建一个列表。此列表应保持不变,直到他们决定从中删除项目。

由于我的列表显示了大量详细信息,因此单个元素可以更改解决方案: - 我将列表数据保存在JSON结构化文件中。并将该文件保存在设备上。 - 每次用户添加或删除项目或更改列表中项目的数据时,我都会对JSONObject进行更改并将其保存到文件中。 - 当用户重新打开应用程序时(可能几天或几秒钟),数据在文件中的JSON结构化字符串中可用。 - 我解析此文件并使用自定义适配器将项目添加到我的列表中。

如果您的待办事项列表每个列表条目只包含简单的单个条目字符串,那么您可以使用简单的csv文件。活动开始后,您将打开该文件。在文件内容中执行拆分,这将为您提供一个字符串数组。您可以使用此数组字符串填充列表。