Samuel Stratford Samuel Stratford - 27 days ago 8
Android Question

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

Answer

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.