Red Junior Red Junior - 5 months ago 31
Java Question

How to save data in a listView

I created a listView that is based on the user input. User has to enter text in an editText and then it's added into the list. It works great. My question though, is how do I save this data so even when they close the app, and then open it back up again, the listView still has the items in it from last time? Here is my code:

MainActivity.java

package com.kass.planner2;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import java.util.ArrayList;

public class MainActivity extends Activity implements View.OnClickListener {

private Button btn;
private EditText et;
private ListView lv;
ArrayList<String> list = new ArrayList<String>();
ArrayAdapter<String> adapter;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btn = (Button)findViewById(R.id.button);
btn.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.listView);
lv.setAdapter(adapter);
}
public void onClick(View v)
{
String input = et.getText().toString();
if(input.length() > 0)
{
// add string to the adapter, not the listview
adapter.add(input);
// no need to call adapter.notifyDataSetChanged(); as it is done by the adapter.add() method
}
}


}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.kass.planner2.MainActivity"
android:weightSum="1">

<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_weight="1.12">

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginTop="60dp"
android:layout_alignEnd="@+id/button" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:onClick="saveEvent"/>

<ListView
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/listView"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_toEndOf="@+id/editText" />
</RelativeLayout>


</LinearLayout>


Thank you.

Answer

You can use either PreferenceManager or an internal SQL database to achieve your task.

Here is an example of how you could use an internal SQL database:

Android comes with an embedded SQLite database. The database needs a table before it can store any input, called “InputTable”. Create a new db folder in the same location as MainActivity.java. Then create a new class called InputContract with the file name InputContract.java:

package com.example.db;

import android.provider.BaseColumns;

public class InputContract {
public static final String DB_NAME = "com.example.db";
public static final int DB_VERSION = 1;

public class TaskEntry implements BaseColumns {
    public static final String TABLE = "tasks";

    public static final String COL_TASK_TITLE = "title";
    }
}

The InputContract class defines constants which are used to access the data in the database. You also need a helper class called InputDbHelper to open the database. Create this class in the db package and add the following code:

package com.example.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class InputDbHelper extends SQLiteOpenHelper {

public InputDbHelper(Context context) {
    super(context, InputContract.DB_NAME, null, InputContract.DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
    String createTable = "CREATE TABLE " + InputContract.TaskEntry.TABLE + "    ( " +
            InputContract.TaskEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
            InputContract.TaskEntry.COL_TASK_TITLE + " TEXT NOT NULL);";

    db.execSQL(createTable);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + InputContract.TaskEntry.TABLE);
    onCreate(db);
}
}

Now you need to adapt MainActivity to store data in the database.

Add a private instance of InputDbHelper in the MainActivity class:

private InputDbHelper mHelper;

Now you need to fetch all the data from the database and show it in the main view.

Replace your onCreate to this:

btn = (Button)findViewById(R.id.button);
btn.setOnClickListener(this);
et = (EditText)findViewById(R.id.editText);
lv=(ListView)findViewById(R.id.listView);
mHelper = new InputDbHelper(this);
updateUI();

Inside your on click method, add the following code:

   String input = et.getText().toString();
   SQLiteDatabase db = mHelper.getWritableDatabase();
   ContentValues values = new ContentValues();
   values.put(InputContract.TaskEntry.COL_TASK_TITLE,   input);     
   db.insertWithOnConflict(InputContract.TaskEntry.TABLE, null, values, SQLiteDatabase.CONFICT_REPLACE);                                        
   db.close();
   updateUI();

Then add the following method to MainActivity to update the UI:

private void updateUI() {

ArrayList<String> taskList = new ArrayList<>();
SQLiteDatabase db = mHelper.getReadableDatabase();
Cursor cursor = db.query(InputContract.TaskEntry.TABLE,
        new String[]{InputContract.TaskEntry._ID, InputContract.TaskEntry.COL_TASK_TITLE},
        null, null, null, null, null);
while (cursor.moveToNext()) {
    int idx = cursor.getColumnIndex(InputContract.TaskEntry.COL_TASK_TITLE);
    taskList.add(cursor.getString(idx));
}

if (adapter== null) {
    adapter= new ArrayAdapter<>(this,  android.R.layout.simple_expandable_list_item_1,
            taskList);
    lv.setAdapter(adapter);
} else {
    adapter.clear();
    adapter.addAll(taskList);
    adapter.notifyDataSetChanged();
}

cursor.close();
db.close();
}

Now, even after the phone completely restarts, the information in the listview will remain.

ADDITION:

If you ever want to delete anything from the database, add the following method:

public void deleteTask() {
SQLiteDatabase db = mHelper.getWritableDatabase();
db.delete(InputContract.TaskEntry.TABLE,
        InputContract.TaskEntry.COL_TASK_TITLE + " = ?",
        new String[]{task});
db.close();
updateUI();

}

Comments