user1334616
user1334616

Reputation:

Populate ListView from database with AsyncTask

What's the most effective solution to implement AsyncTask.

I have a working app where my main activity uses a listView to display results from a database. All of the processing is carried out on the UI thread.

But my current code uses SQLiteDatabase and Cursor objects multiple methods. When initially populating the listview and when deleting rows with the CAB.

The attempts I've made so far have all failed as I'm accessing objects that are still on the UI thread. I'm not sure what approach I should be taking

Below is my code:

/**     * A placeholder fragment containing a simple view. */
public static class PlaceholderFragment extends Fragment {
    /** The fragment argument representing the section number for this fragment. */
    private static final String ARG_SECTION_NUMBER = "section_number";

// TO and FROM arrays are used to map database columns to the corresponding elements on an XML layout file. The layout file is used by the adapter to populate the listView in the main fragment.
static final String[] FROM = { */Colums to query /*}; //end

static final int[] TO = {   */destination colums /* }; // end

    /** Returns a new instance of this fragment for the given section number. */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }
    ListView layoutListView;
    DatabaseHelper DbHelper;
    SQLiteDatabase db;
    Cursor cursor;
    SimpleCursorAdapter adapter;

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

        // Find your views
        layoutListView = (ListView) getView().findViewById(R.id.listView);

        // Create a new helper to control db access and get a readable copy.
        DbHelper = new DatabaseHelper(getActivity());
        db = DbHelper.getReadableDatabase();


    }


    private void updateList(){
        //requery and update cursor
        querydb();
        //tells the adapter the cursor/data has changed
        adapter.notifyDataSetChanged();

    }

    private void querydb() {
        //specify the columns to be used in the db query
        String[] queryColumnList = { */ list of colums to query /*            };

        // Perform a db query and store a table of results in the cursor object
        cursor = db.query(
                DatabaseHelper.dBContract.TABLE_NAME, //table to be queried
                queryColumnList,    //The columns to return
                null,               //The column for the where clause
                null,               //The values for the where clause
                null,               //row grouping
                null,               //filter row groups
                null               //sort order
        );
        //find the layout that will be used for each item in the listview
        int listItemLayoutID = R.layout.row;

        //create a new adapter to deal with the implementation of building a listview
        adapter = new SimpleCursorAdapter(getActivity(), listItemLayoutID, cursor, FROM, TO,2); //Arguments = context, layout for each row, From variable details data source, To variable details the id values of elements in the row layout file.
        //show the adapter which listview it needs to populate
        layoutListView.setAdapter(adapter);


    }
}

}

What I've tried so far:

   private class getListData extends AsyncTask<Void, Void, Void> {


        @Override // Do the long-running work in here
        protected Void doInBackground(Void... Parms) {
            final String[] FROM = { */ source list /*}; //end

            final int[] TO = { */ destination list /* }; // end
            //specify the columns to be used in the db query
            String[] queryColumnList = {
                    dBHelper.dBContract.clutches._ID,
                    dBHelper.dBContract.clutches.C_NAME,
                    dBHelper.dBContract.clutches.C_EGG_COUNT,
                    dBHelper.dBContract.clutches.C_HATCH_START,
                    dBHelper.dBContract.clutches.C_HATCH_END,
            };

            // Perform a db query and store a table of results in the cursor object
            cursor = db.query(
                    TABLE_NAME, //table to be queried
                    queryColumnList,    //The columns to return
                    null,               //The column for the where clause
                    null,               //The values for the where clause
                    null,               //row grouping
                    null,               //filter row groups
                    null               //sort order
            );

        }

        // This is called each time you call publishProgress()
        protected void onProgressUpdate() {
            //setProgressPercent(progress[0]);
        }

        @Override // This is called when doInBackground() is finished
        protected void onPostExecute(Void result) {

            int listItemLayoutID = R.layout.row;

            adapter = new SimpleCursorAdapter(getActivity(), listItemLayoutID, cursor, FROM, TO,2); 
            return null;
            layoutListView.setAdapter(adapter);
        }
    }

EDIT: LogCat

05-21 08:04:44.203 1639-1653/co.uk.tickingClock.app E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1 Process: co.uk.tickingClock.app, PID: 1639 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:300) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) at java.util.concurrent.FutureTask.setException(FutureTask.java:222) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:841) Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() at android.os.Handler.(Handler.java:200) at android.os.Handler.(Handler.java:114) at android.widget.CursorAdapter$ChangeObserver.(CursorAdapter.java:453) at android.widget.CursorAdapter.init(CursorAdapter.java:174) at android.widget.CursorAdapter.(CursorAdapter.java:149) at android.widget.ResourceCursorAdapter.(ResourceCursorAdapter.java:91) at android.widget.SimpleCursorAdapter.(SimpleCursorAdapter.java:104) at co.uk.tickingClock.app.view_clutches$PlaceholderFragment$getListOfClutches.doInBackground(view_clutches.java:282) at co.uk.tickingClock.app.view_clutches$PlaceholderFragment$getListOfClutches.doInBackground(view_clutches.java:256) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.java:237)             at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)             at java.lang.Thread.run(Thread.java:841)

Upvotes: 1

Views: 1136

Answers (1)

Sufian
Sufian

Reputation: 6555

You are initializing your SimpleCursorAdapter in the doInBackground(). Do that in onPostExecute().

Upvotes: 1

Related Questions