Search code examples
androidcursorandroid-cursorloader

How to get a database to show in a pagerAdapter Fragment?


This is code from my Fragment, at present it's not loading anything from the database, which definitely exists. I've been revising it as per kind Edmund's guidance, passing in mCursor, with the whole database table, to mCursorAdapter in the hope that onLoadFinished the adapter would update printing the database to screen. But onLoadFinished() nothing happens :/. Help!

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.quotes.obama.obamaquotes.data.PetContract.PetEntry;
import com.quotes.obama.obamaquotes.data.PetDbHelper;

import static android.content.ContentValues.TAG;

//import android.content.CursorLoader;

/**
 * Created by Sam on 30/10/2016.
 */
public class AllQuotesFragment extends Fragment implements
        LoaderManager.LoaderCallbacks<Cursor> { //}, android.support.v4.app.LoaderManager.LoaderCallbacks<Object> {

    /** Identifier for the pet data loader */
    private static final int PET_LOADER = 0;

    /** Adapter for the ListView */
    PetCursorAdapter mCursorAdapter;

    /** so know when we have the database ready for display */
    static Boolean databaseLoaderComplete = false;

    public AllQuotesFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @return A new instance of fragment GameFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static AllQuotesFragment newInstance() {
        AllQuotesFragment fragment = new AllQuotesFragment();
        //Bundle args = new Bundle();
        //args.putString(TITLE, pageTitle);
        return fragment;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_quotes_all, container, false);
        // inflate fragment_game into "container",

        // Find the ListView which will be populated with the pet data
        ListView petListView = (ListView) rootView.findViewById(R.id.list);

        // Find and set empty view on the ListView, so that it only shows when the list has 0 items.
        View emptyView = rootView.findViewById(R.id.empty_view);
        petListView.setEmptyView(emptyView);

        /* as per Edmund
        * http://stackoverflow.com/questions/40517872/how-to-wait-for-cursorloader-to-complete/40530754?noredirect=1#comment68332991_40530754 */

        // To access our database, we instantiate our subclass of SQLiteOpenHelper
        // and pass the context, which is the current activity.
        PetDbHelper mDbHelper = new PetDbHelper(getContext());

        // Create and/or open a database to read from it
        SQLiteDatabase db = mDbHelper.getReadableDatabase();

        // Perform this raw SQL query "SELECT * FROM pets"
        // to get a Cursor that contains all rows from the pets table.
        Cursor mCursor = db.rawQuery("SELECT * FROM " + PetEntry.TABLE_NAME, null);


        // Setup an Adapter to create a list item for each row of pet data in the Cursor.
        // There is no pet data yet (until the loader finishes) so pass in null for the Cursor.
        mCursorAdapter = new PetCursorAdapter(getContext(), mCursor); // was null
        petListView.setAdapter(mCursorAdapter);

        // TODO Setup the item click listener?
        Log.w(TAG, "about to initLoader");
        // Kick off the loader, need activity to get Context

        getLoaderManager().initLoader(PET_LOADER, null, this);

        Log.w(TAG, "All Quotes UI created, returning ");
        return rootView;

    }
    @Override
    public android.support.v4.content.Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        // Define a projection that specifies the columns from the table we care about.
        Log.i(TAG, "creating a loader");

        String[] projection = {
                PetEntry._ID,
                PetEntry.COLUMN_PET_NAME,
                PetEntry.COLUMN_PET_BREED };


        // This loader will execute the ContentProvider's query method on a background thread
        return new CursorLoader(getContext(),   // Parent activity context
                PetEntry.CONTENT_URI,   // Provider content URI to query
                projection,             // Columns to include in the resulting Cursor
                null,                   // No selection clause
                null,                   // No selection arguments
                null);                  // Default sort order

    }

    @Override
    public void onLoadFinished(android.support.v4.content.Loader<Cursor> loader, Cursor data) {
        // Update {@link PetCursorAdapter} with this new cursor containing updated pet data
        mCursorAdapter.swapCursor(data);
        Log.i(TAG, "database updated");
    }

    @Override
    public void onLoaderReset(android.support.v4.content.Loader<Cursor> loader) {
        // Callback called when the data needs to be deleted
        mCursorAdapter.swapCursor(null);
        Log.i(TAG, "database reset");
    }

Solution

  • The fragment "winning" shouldn't be a problem as onLoadFinished() should load the cursor data after the fragment is displayed.

    Replace:

    getActivity().getLoaderManager()
    

    with:

    getLoaderManager()
    

    and make sure you're using the support LoaderManager with a support Fragment.

    Also, pass the cursor rather than null into the adapter constructor.