如何在使用Loader自动插入数据库后加载listview中的数据?

时间:2014-12-15 11:38:54

标签: android sqlite android-asynctask loader asynctaskloader

我创建了一个演示应用程序,它将一些数据插入sqlite数据库并在listview [Fragment]上更新。但我想通过点击按钮添加另一个数据,该数据来自EditText,并使用新数据更新listview。

我在下面写下我的演示代码。请告诉我如何在listview中显示同时添加到数据库中的所有数据。

####################################### 步骤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);

}
####################################### 第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 + "]";
    }
}
####################################################
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;
    }
}
####################################### 第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);
    }

}
##############################################
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();
    }

}
##############################################
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);
            }
        }
    }
}
##############################################
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);
        }
    }
}
###############################################
<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>
#############################################
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;
        }

    }
}
###############################################
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;
    }
}

每当我在edittext中写一些内容并单击Add按钮时,它只将数据存储到数据库中,但它不会更新到我们在那里显示的listview。 请检查我在哪里弄错???

1 个答案:

答案 0 :(得分:0)

onClick

内的主要活动中添加此行
getLoaderManager().restartLoader(0,null,this);