How to load data in listview after inserting into database using Loader automatically?

799 Views Asked by At

I've created demo application which insert some data into sqlite database and update on listview [Fragment]. But i want to add one another data by click on button which data comes from EditText and update on listview with new data.

I write my demo code below. pls let me know how do i show all data in listview which after adding into database at the same time.

####################################### Step 1
package com.example.locationsample.database;

import java.util.List;

import android.database.sqlite.SQLiteDatabase;

public abstract class DataSource<T> {

    public final SQLiteDatabase mDatabase;

    public DataSource(final SQLiteDatabase database) {
        mDatabase = database;
    }

    public abstract boolean insert(T entity);

    public abstract boolean delete(T entity);

    public abstract boolean update(T entity);

    public abstract List read();

    public abstract List read(String selection, String[] selectionArgs,
            String groupBy, String having, String orderBy);

}
####################################### Step 2
package com.example.locationsample.model;

public class Test {

    public Test() {
    }

    public Test(String name) {
        this.name = name;
    }

    private int id;
    private String name;

    /**
     * @return the id
     */
    public int getId() {
        return id;
    }

    /**
     * @param id
     *            the id to set
     */
    public void setId(final int id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            the name to set
     */
    public void setName(final String name) {
        this.name = name;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return name;
        // return "Test [name=" + name + "]";
    }
}
####################################### Step 3
package com.example.locationsample.database;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.example.locationsample.model.Test;

public class TestDataSource extends DataSource<Test> {

    public static final String TABLE_NAME = "test";
    private static final String COLUMN_ID = "_id";
    private static final String COLUMN_NAME = "name";

    public static final String CREATE_COMMAND = "create table " + TABLE_NAME
            + " (" + COLUMN_ID + " integer primary key autoincrement, "
            + COLUMN_NAME + " text not null);";

    public TestDataSource(final SQLiteDatabase database) {
        super(database);
    }

    @Override
    public boolean insert(final Test entity) {

        if (entity == null) {
            return false;
        }
        final long result = mDatabase.insert(TABLE_NAME, null,
                generateContentValueFromObject(entity));
        return result != -1;
    }

    @Override
    public boolean delete(final Test entity) {

        if (entity == null) {
            return false;
        }
        final int result = mDatabase.delete(TABLE_NAME, COLUMN_ID + "=?",
                new String[] { String.valueOf(entity.getId()) });
        return result != 0;
    }

    @Override
    public boolean update(final Test entity) {

        if (entity == null) {
            return false;
        }
        final int result = mDatabase.update(TABLE_NAME,
                generateContentValueFromObject(entity), COLUMN_ID + "=?",
                new String[] { String.valueOf(entity.getId()) });
        return result != 0;
    }

    @Override
    public List<Test> read() {

        final Cursor cursor = mDatabase.query(TABLE_NAME, getAllColumns(),
                null, null, null, null, null);

        final List<Test> tests = new ArrayList<Test>();
        if (cursor != null && cursor.moveToFirst()) {
            while (!cursor.isAfterLast()) {
                tests.add(generateObjectFromCursor(cursor));
                cursor.moveToNext();
            }
            cursor.close();
        }
        return tests;
    }

    @Override
    public List<Test> read(final String selection,
            final String[] selectionArgs, final String groupBy,
            final String having, final String orderBy) {

        final Cursor cursor = mDatabase.query(TABLE_NAME, getAllColumns(),
                selection, selectionArgs, groupBy, having, orderBy);

        final List<Test> tests = new ArrayList<Test>();
        if (cursor != null && cursor.moveToFirst()) {
            while (!cursor.isAfterLast()) {
                tests.add(generateObjectFromCursor(cursor));
                cursor.moveToNext();
            }
            cursor.close();
        }
        return tests;
    }

    private String[] getAllColumns() {
        return new String[] { COLUMN_ID, COLUMN_NAME };
    }

    private Test generateObjectFromCursor(final Cursor cursor) {
        if (cursor == null) {
            return null;
        }
        final Test test = new Test();
        test.setId(cursor.getInt(cursor.getColumnIndex(COLUMN_ID)));
        test.setName(cursor.getString(cursor.getColumnIndex(COLUMN_NAME)));
        return test;
    }

    private ContentValues generateContentValueFromObject(final Test entity) {
        if (entity == null) {
            return null;
        }
        final ContentValues values = new ContentValues();
        values.put(COLUMN_NAME, entity.getName());
        return values;
    }
}
####################################### Step 4
package com.example.locationsample.database;

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

public class DbHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "test.db";
    private static final int DATABASE_VERSION = 1;

    public DbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(TestDataSource.CREATE_COMMAND);
    }

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

}
####################################### Step 5
package com.example.locationsample.loader;

import android.content.Loader;
import android.os.AsyncTask;
import android.util.Log;

public abstract class ContentChangingTask<T1, T2, T3> extends
        AsyncTask<T1, T2, T3> {

    private static final String TAG = "ContentChangingTask";

    private Loader<?> mLoader = null;

    public ContentChangingTask(final Loader<?> loader) {
        mLoader = loader;
    }

    @Override
    protected void onPostExecute(final T3 result) {
        // super.onPostExecute(result);
        Log.i(TAG, "+++ onPostExecute() called! +++");
        mLoader.onContentChanged();
    }

}
####################################### Step 6
package com.example.locationsample.loader;

import java.util.List;

import android.content.AsyncTaskLoader;
import android.content.Context;
import android.util.Log;

public abstract class AbstractDataLoader<E extends List<?>> extends
        AsyncTaskLoader<E> {

    private static final String TAG = "AbstractDataLoader";

    protected E mLastDataList = null;

    protected abstract E buildList();

    public AbstractDataLoader(final Context context) {
        super(context);
    }

    /**
     * Runs on a worker thread, loading in our data. Delegates the real work to
     * concrete subclass' buildList() method.
     */
    @Override
    public E loadInBackground() {
        Log.d(TAG, "+++ loadInBackground() called! +++");
        return buildList();
    }

    /**
     * Runs on the UI thread, routing the results from the background thread to
     * whatever is using the dataList.
     */
    @Override
    public void deliverResult(final E dataList) {
        Log.d(TAG, "+++ deliverResult() called! +++");
        if (isReset()) {
            // An async query came in while the loader is stopped
            emptyDataList(dataList);
            return;
        }
        final E oldDataList = mLastDataList;
        mLastDataList = dataList;
        if (isStarted()) {
            super.deliverResult(dataList);
        }
        if (oldDataList != null && oldDataList != dataList
                && oldDataList.size() > 0) {
            emptyDataList(oldDataList);
        }
    }

    /**
     * Starts an asynchronous load of the list data. When the result is ready
     * the callbacks will be called on the UI thread. If a previous load has
     * been completed and is still valid the result may be passed to the
     * callbacks immediately.
     * 
     * Must be called from the UI thread.
     */
    @Override
    protected void onStartLoading() {
        //super.onStartLoading();
        Log.d(TAG, "+++ onStartLoading() called! +++");
        if (mLastDataList != null) {
            deliverResult(mLastDataList);
        }
        if (takeContentChanged() || mLastDataList == null
                || mLastDataList.size() == 0) {
            forceLoad();
        }
    }

    /**
     * Must be called from the UI thread, triggered by a call to stopLoading().
     */
    @Override
    protected void onStopLoading() {
        Log.d(TAG, "+++ onStopLoading() called! +++");
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    /**
     * Must be called from the UI thread, triggered by a call to cancel(). Here,
     * we make sure our Cursor is closed, if it still exists and is not already
     * closed.
     */
    @Override
    public void onCanceled(final E dataList) {
        Log.d(TAG, "+++ onCanceled() called! +++");
        if (dataList != null && dataList.size() > 0) {
            emptyDataList(dataList);
        }
    }

    /**
     * Must be called from the UI thread, triggered by a call to reset(). Here,
     * we make sure our Cursor is closed, if it still exists and is not already
     * closed.
     */
    @Override
    protected void onReset() {
        super.onReset();
        Log.d(TAG, "+++ onReset() called! +++");
        // Ensure the loader is stopped
        onStopLoading();
        if (mLastDataList != null && mLastDataList.size() > 0) {
            emptyDataList(mLastDataList);
        }
        mLastDataList = null;
    }

    protected void emptyDataList(final E dataList) {

        if (dataList != null && dataList.size() > 0) {
            for (int i = 0; i < dataList.size(); i++) {
                dataList.remove(i);
            }
        }
    }
}
####################################### Step 7
package com.example.locationsample.loader;

import java.util.List;

import android.content.Context;
import android.util.Log;

import com.example.locationsample.database.DataSource;
import com.example.locationsample.model.Test;

public class SQLiteTestDataLoader extends AbstractDataLoader<List<Test>> {

    private static final String TAG = "SQLiteTestDataLoader";

    private final DataSource<Test> mDataSource;
    private String mSelection;
    private String[] mSelectionArgs;
    private String mGroupBy;
    private String mHaving;
    private String mOrderBy;

    public SQLiteTestDataLoader(final Context context,
            final DataSource<Test> dataSource, final String selection,
            final String[] selectionArgs, final String groupBy,
            final String having, final String orderBy) {
        super(context);
        mDataSource = dataSource;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected List<Test> buildList() {
        final List<Test> testList = mDataSource.read(mSelection,
                mSelectionArgs, mGroupBy, mHaving, mOrderBy);
        return testList;
    }

    public void insert(final Test entity) {
        new InsertTask(this).execute(entity);
    }

    public void update(final Test entity) {
        new UpdateTask(this).execute(entity);
    }

    public void delete(final Test entity) {
        new DeleteTask(this).execute(entity);
    }

    private class InsertTask extends ContentChangingTask<Test, Void, Void> {

        InsertTask(final SQLiteTestDataLoader loader) {
            super(loader);
        }

        @Override
        protected Void doInBackground(final Test... params) {
            Log.i(TAG, "+++ Inserting... +++");
            mDataSource.insert(params[0]);
            return (null);
        }
    }

    private class UpdateTask extends ContentChangingTask<Test, Void, Void> {

        UpdateTask(final SQLiteTestDataLoader loader) {
            super(loader);
        }

        @Override
        protected Void doInBackground(final Test... params) {
            Log.i(TAG, "+++ Updating... +++");
            mDataSource.update(params[0]);
            return (null);
        }
    }

    private class DeleteTask extends ContentChangingTask<Test, Void, Void> {

        DeleteTask(final SQLiteTestDataLoader loader) {
            super(loader);
        }

        @Override
        protected Void doInBackground(final Test... params) {
            Log.i(TAG, "+++ Deleting... +++");
            mDataSource.delete(params[0]);
            return (null);
        }
    }
}
####################################### Step 8
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/txt_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <EditText
        android:id="@+id/edtxt_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_toLeftOf="@+id/btn_add"
        android:inputType="text"
        android:labelFor="@+id/edtxt_add" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="ADD" />

    <fragment
        android:id="@+id/titles"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/btn_add"
        android:layout_below="@id/txt_data"
        class="com.example.locationsample.MainFragment" />

</RelativeLayout>
####################################### Step 9
package com.example.locationsample;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;

import com.example.locationsample.database.DbHelper;
import com.example.locationsample.database.TestDataSource;
import com.example.locationsample.loader.SQLiteTestDataLoader;
import com.example.locationsample.model.Test;
import com.example.locationsample.utilities.Utils;

public class MainActivity extends Activity implements 
        OnClickListener {

    private static final String TAG = "MainActivity";
    private TextView mTxtData;

    private EditText mEdTxtAdd;

    private LocationManager mLocationManager;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTxtData = (TextView) findViewById(R.id.txt_data);
        mEdTxtAdd = (EditText) findViewById(R.id.edtxt_add);
        findViewById(R.id.btn_add).setOnClickListener(this);


        DbHelper helper = new DbHelper(MainActivity.this);
        SQLiteDatabase database = helper.getWritableDatabase();
        TestDataSource dataSource = new TestDataSource(database);
        List<Test> testList = dataSource.read();
        if (testList == null || testList.size() == 0) {
            dataSource.insert(new Test("11111"));
            dataSource.insert(new Test("22222"));
            dataSource.insert(new Test("33333"));
        }
        database.close();
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {

        case R.id.btn_add:

            if (mEdTxtAdd == null
                    || TextUtils.isEmpty(mEdTxtAdd.getText().toString())) {
                return;
            }

            DbHelper helper = new DbHelper(MainActivity.this);
            SQLiteDatabase database = helper.getWritableDatabase();
            TestDataSource dataSource = new TestDataSource(database);

            SQLiteTestDataLoader loader = new SQLiteTestDataLoader(
                    MainActivity.this, dataSource, null, null, null, null, null);
            loader.insert(new Test(mEdTxtAdd.getText().toString()));
            break;

        default:
            break;
        }

    }
}
####################################### Step 10
package com.example.locationsample;

import java.util.List;

import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Loader;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;

import com.example.locationsample.database.DbHelper;
import com.example.locationsample.database.TestDataSource;
import com.example.locationsample.loader.SQLiteTestDataLoader;
import com.example.locationsample.model.Test;

public class MainFragment extends ListFragment implements
        LoaderCallbacks<List<Test>> {

    private ArrayAdapter<Test> mAdapter;
    // The Loader's id (this id is specific to the ListFragment's LoaderManager)
    private static final int LOADER_ID = 1;
    private static final boolean DEBUG = true;
    private static final String TAG = "MainFragment";
    private SQLiteDatabase mDatabase;
    private TestDataSource mDataSource;
    private DbHelper mDbHelper;

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

        mDbHelper = new DbHelper(getActivity());
        mDatabase = mDbHelper.getWritableDatabase();
        mDataSource = new TestDataSource(mDatabase);

        mAdapter = new ArrayAdapter<Test>(getActivity(),
                android.R.layout.simple_list_item_1);
        setEmptyText("No data, please add from menu.");

        setListAdapter(mAdapter);
        setListShown(false);

        if (DEBUG) {
            Log.i(TAG, "+++ Calling initLoader()! +++");
            if (getLoaderManager().getLoader(LOADER_ID) == null) {
                Log.i(TAG, "+++ Initializing the new Loader... +++");
            } else {
                Log.i(TAG,
                        "+++ Reconnecting with existing Loader (id '1')... +++");
            }
        }
        // Initialize a Loader with id '1'. If the Loader with this id already
        // exists, then the LoaderManager will reuse the existing Loader.
        getLoaderManager().initLoader(LOADER_ID, null, this);
    }

    @Override
    public Loader<List<Test>> onCreateLoader(final int id, final Bundle arg1) {
        final SQLiteTestDataLoader loader = new SQLiteTestDataLoader(
                getActivity(), mDataSource, null, null, null, null, null);
        return loader;
    }

    @Override
    public void onLoadFinished(final Loader<List<Test>> loader,
            final List<Test> data) {
        Log.d(TAG, "+++### onLoadFinished() called! ###+++");
        if (DEBUG)
            Log.i(TAG, "+++ onLoadFinished() called! +++");
        mAdapter.clear();
        for (final Test test : data) {
            mAdapter.add(test);
        }
        if (isResumed()) {
            setListShown(true);
        } else {
            setListShownNoAnimation(true);
        }
    }

    @Override
    public void onLoaderReset(final Loader<List<Test>> arg0) {
        Log.i(TAG, "+++ onLoadReset() called! +++");
        mAdapter.clear();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mDbHelper.close();
        mDatabase.close();
        mDataSource = null;
        mDbHelper = null;
        mDatabase = null;
    }
}
#

Whenever i write something in edittext and click on Add button, it stores data only to database, But it doesn't any update into listview which we are showing at there. Pls, check where do i mistake???

1

There are 1 best solutions below

1
On

Add this line in the main activity inside the onClick

getLoaderManager().restartLoader(0,null,this);