Search code examples
android-fragmentsandroid-sqliteandroid-gridviewandroid-cursoradapterandroid-cursorloader

How to get GridView and GridView Item to Inflate in a Fragment while using Custom CursorAdapter and Cursor Loader?


I am brand new to Android programming and StackOverFlow. I am working on a journal/tracking app with multiple activities that takes user entries to obtain data and is backed by internal SQLite Database. I am using a custom CursorAdapter so I can make adjustments for images and Loader Manager to manage the database off the UI thread.

The difficulty I am having is getting a GridView to inflate in one fragment of my main activity. The database insertion seems to be working fine, however the GridView is not inflated, I only see a blank screen(the background shows). I have tried changing the fragment containers, and the layout parameters, but these lead to errors and still no GridView. I have tried adjusting the CursorAdaptor parameters - including null, this, or getContext. I have tried attaching the fragment by layout only and attaching programmatically. It is possible there is an error in my fragment attachment because I am still not sure about this. I have included a lot of code because I don't know where the issue is.

I am not getting any errors on the project build currently. Any ideas to what I am doing wrong? Help would be greatly appreciated.

Here is my main Activity which has two fragments MyCritter and KeepMyCritters(GridView). I omitted toolbars and buttons-these work fine.

public class MyCritter extends Critters implements        KeepMyCritters.OnFragmentInteractionListener,LoaderManager.LoaderCallbacks<Cursor> {

private KeepMyCritters critterFragment;
private Intent intent;

public CursorAdapter cursorAdapter;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my_critters);


    cursorAdapter = new CritterCursorAdapter(this, null, 0);

    getSupportLoaderManager().initLoader(0,null,this);

    InsertNewCritter(_id, "Sherman");
    InsertNewCritter(_id,"Charlie");

  critterFragment = new KeepMyCritters();
   setFragment(critterFragment);

}

public void setFragment(Fragment frag){
    FragmentManager fm = getSupportFragmentManager();
    fm.findFragmentById(R.id.container);
    if (frag == null) {fm.beginTransaction().add(R.id.container, critterFragment).commit();

}

@Override
public void onFragmentInteraction(long _id) {
    Toast.makeText(getApplicationContext(),"You selected a Critter to View", Toast.LENGTH_LONG).show();
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
 CursorLoader cursorLoader = new CursorLoader(this, CritterProvider.CONTENT_URI, null, null, null, null);
    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    cursorAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    cursorAdapter.swapCursor(null);
}

}

Here is my KeepMyCritters Fragment

public class KeepMyCritters extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>,AdapterView.OnItemClickListener{


CritterCursorAdapter cursorAdapter;

private OnFragmentInteractionListener mListener;

public KeepMyCritters() {
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_keep_my_critters, container, false);

    cursorAdapter = new CritterCursorAdapter(getContext(), (Cursor)CritterProvider.CONTENT_URI,0);

    GridView gv =(GridView) view.findViewById(R.id.gridview);


    gv.setAdapter(cursorAdapter);
    gv.setOnItemClickListener(this);

    getLoaderManager().initLoader(0,null,this);
    return view;

}


@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onDetach(){
    super.onDetach();
    mListener=null;

}

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
    Uri CritterUri = ContentUris.withAppendedId(CritterProvider.CONTENT_URI, l );
    if(mListener !=null) {
        mListener.onFragmentInteraction(l);
    }
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(getContext(), CritterProvider.CONTENT_URI, null, null, null, null);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    cursorAdapter.swapCursor(cursor);

}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    cursorAdapter.swapCursor(null);

}


public interface OnFragmentInteractionListener {

    void onFragmentInteraction(long id);
}

}

Here is my custom CursorAdapter class

public class CritterCursorAdapter extends CursorAdapter {
public CritterCursorAdapter(Context context, Cursor cursor, int flags) {
    super(context, cursor, flags);
}

Context c;
private LayoutInflater inflater;
 private GridView gv;


@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
    return inflater.inflate(R.layout.fragment_item_grid, gv);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {

    String name = cursor.getString(
            cursor.getColumnIndex(CritterDatabaseHelper.NAME));

    TextView hName = (TextView) view.findViewById(R.id.critterName);
    hName.setText(name);

}

}

The database has an _id column and in the debugger it shows the entries are inserted correctly.

The insertCritter code :

protected void InsertNewCritter(int _id, String name) {
    ContentValues values = new ContentValues();
    values.put(CrittersDatabaseHelper.NAME, name);

    Uri crittersUri = getContentResolver().insert(CritterProvider.CONTENT_URI, values);
    Log.d("MyCritter", "Inserted data " + crittersUri.getLastPathSegment());
}

The content provider:

public class CritterProvider extends ContentProvider {

private static final String AUTHORITY = mypackage.critterProvider";
private static final String BASE_PATH = "critters";

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

private static final int CRITTERS = 1;
private static final int CRITTERS_ID = 2;

private static final UriMatcher uriMatcher =
        new UriMatcher(UriMatcher.NO_MATCH);

static {
    uriMatcher.addURI(AUTHORITY, BASE_PATH, CRITTERS);
    uriMatcher.addURI(AUTHORITY, BASE_PATH + " /# ", CRITTERS_ID);
}


private SQLiteDatabase db;

@Override
public boolean onCreate() {
    CrittersDatabaseHelper cdb = new CrittersDatabaseHelper(getContext());
    db = cdb.getWritableDatabase();
    return true;
}


@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String selection, String[] selectionArgs, String sortOrder) {
    return db.query(CrittersDatabaseHelper.TABLE_MAIN, CrittersDatabaseHelper.ALL_TABLE_MAIN_COLUMNS, selection, selectionArgs, null, null, null);
}

@Override
public String getType(Uri uri) {
    return null;
}

@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
    long id = db.insert(CrittersDatabaseHelper.TABLE_MAIN, null, values);
    return Uri.parse(BASE_PATH + "/" + id);

}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    return db.delete(CrittersDatabaseHelper.TABLE_MAIN, selection, selectionArgs);
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    return db.update(CrittersDatabaseHelper.TABLE_MAIN, values, selection, selectionArgs);
}

}

Finally here are the layout files:

MyCritter (MainActivity) xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout     xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="@color/colorPrimaryDark"
tools:context="com.mypackage.Activities.MyCritters">


<HorizontalScrollView
    android:layout_width="wrap_content"
    android:layout_height="match_parent">



    <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:orientation="horizontal">

        <include layout="@layout/content_my_critter"
         android:layout_height="match_parent"
         android:layout_width="422dp" />

        <include layout="@layout/fragment_keep_my_critters"
            android:layout_height="match_parent"
            android:layout_width="422dp"/>

    </LinearLayout>

</HorizontalScrollView>

KeepMyCritters Fragment xml:

<FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/jungle"
tools:context="com.mypackage.Fragments.KeepMyCritters"
tools:showIn="@layout/activity_my_critter">


<TextView
    android:text="My Critters"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/textView"
    android:textAppearance="@style/TextAppearance.AppCompat.Display1"
    android:gravity="center"
    android:textColor="@color/colorAccent" />

<GridView
    android:id="@+id/gridview"
    android:layout_width="match_parent"
    android:layout_height="546dp"
    android:columnWidth="120dp"
    android:numColumns="auto_fit"
    android:verticalSpacing="30dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
    android:layout_alignParentBottom="true" />


</FrameLayout>

My gridview - item xml:

?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_item_grid"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:showIn="@layout/fragment_keep_my_critters">


<TextView
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:id="@+id/critterName"
    android:layout_weight="1"
    android:textAppearance="@style/TextAppearance.AppCompat.Display1"
    android:gravity="center"
    android:textColor="#3bae1b"
    android:textStyle="normal|bold|italic" />


</LinearLayout>


Solution

  • I believe the issue is I was using a coordinator layout with the GridView. I have now seen prior posts explaining that the coordinator layout and Gridview dont work together. There were several workarounds presented but I could not figure out how to implement these with my particular project. I scrapped the coordinator layout and got the gridview to work properly. I did have an issue with trying to cast a uri to cursor in the cursor adapter which I changed to get it to work. I am still open to other solutions to get these to work together because the coordinator layout is smooth and more precise appearing.