Using the recyclerview with a database

Currently there is no default implementation of RecyclerView.Adapter available.

May be with the official release, Google will add it.

Since there is no support for CursorAdapter with the recyclerview currently, how can we use a recyclerview with a database ? Any suggestions ?

--------------Solutions-------------

If you are running a query with a CursorLoader and you want RecyclerView instead of ListView.

You can try my CursorRecyclerViewAdapter: CursorAdapter in RecyclerView

My trick was to hold a CursorAdapter member in my recyclerView.Adapter implementation. then passing all the handling of creating the new view & binding it to the cursor adapter, something like this:

public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder {

// PATCH: Because RecyclerView.Adapter in its current form doesn't natively support
// cursors, we "wrap" a CursorAdapter that will do all teh job
// for us
CursorAdapter mCursorAdapter;

Context mContext;

public MyRecyclerAdapter(Context context, Cursor c) {

mContext = context;

mCursorAdapter = new CursorAdapter(mContext, c, 0) {

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// Inflate the view here
}

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

}
};
}

public static class ViewHolder extends RecyclerView.ViewHolder{

View v1;

public ViewHolder(View itemView) {
super(itemView);
v1 = itemView.findViewById(R.id.v1);
}
}

@Override
public int getItemCount() {
return mCursorAdapter.getCount();
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Passing the binding operation to cursor loader
mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());

}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Passing the inflater job to the cursor-adapter
View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
return new ViewHolder(v);
}

}

You can implement all the required methods yourself. I recently made my own implementation by just copy pasting code from CursorAdapter.

public class MyAdapter extends RecyclerView.Adapter<ViewHolder> {

protected boolean mDataValid;
protected boolean mAutoRequery;
protected Cursor mCursor;
protected Context mContext;
protected int mRowIDColumn;
protected ChangeObserver mChangeObserver;
protected DataSetObserver mDataSetObserver;
protected FilterQueryProvider mFilterQueryProvider;
public static final int FLAG_AUTO_REQUERY = 0x01;
public static final int FLAG_REGISTER_CONTENT_OBSERVER = 0x02;

public Cursor getCursor() {
return mCursor;
}

//Recommended
public MyAdapter(Context context, Cursor c, int flags) {
init(context, c, flags);
}

public MyAdapter(Context context, Cursor c) {
init(context, c, FLAG_AUTO_REQUERY);
}

public MyAdapter(Context context, Cursor c, boolean autoRequery) {
init(context, c, autoRequery ? FLAG_AUTO_REQUERY : FLAG_REGISTER_CONTENT_OBSERVER);
}

void init(Context context, Cursor c, int flags) {
if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) {
flags |= FLAG_REGISTER_CONTENT_OBSERVER;
mAutoRequery = true;
} else {
mAutoRequery = false;
}
boolean cursorPresent = c != null;
mCursor = c;
mDataValid = cursorPresent;
mContext = context;
mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) {
mChangeObserver = new ChangeObserver();
mDataSetObserver = new MyDataSetObserver();
} else {
mChangeObserver = null;
mDataSetObserver = null;
}

if (cursorPresent) {
if (mChangeObserver != null) c.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver);
}
}

// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent,
int viewType) {
// create a new view
final View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
// set the view's size, margins, paddings and layout parameters

ViewHolder vh = new ViewHolder(view, mCursor, new ViewHolder.IMyViewHolderClicks() {

@SuppressLint("NewApi")
@Override
public void onClick(Cursor cursor) {
Log.e("Item :", cursor.getString(cursor.getColumnIndex(MyDatabaseHelper.MW_NAAM)));
Intent intent = new Intent(TasksListFragment.this.getActivity(), DetailActivity.class);
intent.putExtra(DetailActivity.EXTRA_PARAM_ID, cursor.getLong(cursor.getColumnIndex(MyDatabaseHelper.MW_ID)));

ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
TasksListFragment.this.getActivity(),

// Now we provide a list of Pair items which contain the view we can transitioning
// from, and the name of the view it is transitioning to, in the launched activity
new Pair<View, String>(
view.findViewById(R.id.imageview_item),
DetailActivity.VIEW_NAME_HEADER_IMAGE),
new Pair<View, String>(
view.findViewById(R.id.textview_name),
DetailActivity.VIEW_NAME_HEADER_TITLE)
);

// Now we can start the Activity, providing the activity options as a bundle
startActivity(intent, activityOptions.toBundle());
// END_INCLUDE(start_activity)
}
});
return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@SuppressLint("NewApi")
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final Cursor cursor = getItem(position);

holder.mTextView.setText(cursor.getString(cursor.getColumnIndex(MyDatabaseHelper.MW_NAAM)));
holder.mImageView.setTransitionName("grid:image:" + cursor.getLong(cursor.getColumnIndex(MyDatabaseHelper.MW_ID)));
holder.mTextView.setTransitionName("grid:name:" + cursor.getLong(cursor.getColumnIndex(MyDatabaseHelper.MW_ID)));
}

//@Override
// public View getView(int position, View view, ViewGroup viewGroup) {
// return view;
// }

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return getCount();
}

public int getCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
} else {
return 0;
}
}

public Cursor getItem(int position) {
if (mDataValid && mCursor != null) {
mCursor.moveToPosition(position);
return mCursor;
} else {
return null;
}
}

@Override
public long getItemId(int position) {
if (mDataValid && mCursor != null) {
if (mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIDColumn);
} else {
return 0;
}
} else {
return 0;
}
}

public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
if (oldCursor != null) {
if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);
if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
mCursor = newCursor;
if (newCursor != null) {
if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);
mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
// notify the observers about the new cursor
notifyDataSetChanged();
} else {
mRowIDColumn = -1;
mDataValid = false;
// notify the observers about the lack of a data set
notifyDataSetInvalidated();
}
return oldCursor;
}

public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}

public CharSequence convertToString(Cursor cursor) {
return cursor == null ? "" : cursor.toString();
}

public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (mFilterQueryProvider != null) {
return mFilterQueryProvider.runQuery(constraint);
}
return mCursor;
}

public FilterQueryProvider getFilterQueryProvider() {
return mFilterQueryProvider;
}

public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
mFilterQueryProvider = filterQueryProvider;
}

protected void onContentChanged() {
if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {
if (false) Log.v("Cursor", "Auto requerying " + mCursor + " due to update");
mDataValid = mCursor.requery();
}
}

private class ChangeObserver extends ContentObserver {
public ChangeObserver() {
super(new Handler());
}

@Override
public boolean deliverSelfNotifications() {
return true;
}

@Override
public void onChange(boolean selfChange) {
onContentChanged();
}
}

private class MyDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
mDataValid = true;
notifyDataSetChanged();
}

@Override
public void onInvalidated() {
mDataValid = false;
notifyDataSetInvalidated();
}
}

private final DataSetObservable mDataSetObservable = new DataSetObservable();

public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}

public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}

public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
}

You have simply to follow these steps:

  • In the recycler view.adapter, create an ArrayList or an Iterator initialized with a null value.
  • Create a method like the ex swapcursor, for example swapdata(Arraylist<T> data). Inside you give a new values to the array list, iterator or any structure that system can iterate using the integer position int the bindview. The values of this method are passed in the onloaderfinished(). Then call in just after assignement notifydatachange(); these will ask the RecyclerView to redraw all the list with new data of the ArrayList.

In the activity or fragment where you are using the loadercalback, create a method that transforms the cursor to an arraylist, or iterator, depending on the data structure chosen in the adapter.

This way you can always use the loadercalback with out blocking the main thread.

I just used a class that I made that holds the data items I need to display for each item (CardView) in the list. I have a recycler view full of cardviews with 4 textviews in each. This class is called "Card". It only holds the strings needed to populate the textviews. I get a cursor to the data items I need, then construct a card object from each cursor result. These card objects are added to a list which is passed to my Adapter (which is a subclass of RecyclerView.Adapter). and then viewholder binding goes from there. See this Link

Category:android Time:2014-10-22 Views:6

Related post

  • storing files to a database or just to the local hard-disk? 2008-08-06

    So I'm using an app that stores images heavily in the DB. What's your outlook on this? I'm more of a type to store the location in the filesystem, than store it directly in the DB. What do you think are the pros/cons? --------------Solutions---------

  • MOSS SSP Issue - Failed database logons from deleted SSP 2008-08-07

    We've been having some issues with a SharePoint instance in a test environment. Thankfully this is not production ;) The problems started when the disk with the SQL Server databases and search index ran out of space. Following this, the search servic

  • How much database performance overhead when using LINQ? 2008-08-07

    How much database performance overhead is involved with using C# and LINQ compared to custom optimized queries loaded with mostly low-level C, both with a SQL Server 2008 backend? I'm specifically thinking here of a case where you have a fairly data-

  • What point should someone decide to switch Database Systems 2008-08-07

    When developing whether its Web or Desktop at which point should a developer switch from SQLite, MySQL, MS SQL, etc --------------Solutions------------- It depends on what you are doing. You might switch if: You need more scalability or better perfor

  • Locking a SQL Server Database with PHP 2008-08-07

    I'm wanting extra security for a particular point in my web app. So I want to lock the database (SQL Server 2005). Any suggestions or is this even necessary with SQL Server? Edit on question: The query is failing silently with no errors messages logg

  • Inheritance in database? 2008-08-08

    Is there any way to use inheritance in database (Specifically in SQL Server 2005)? Suppose I have few field like CreatedOn, CreatedBy which I want to add on all of my entities. I looking for an alternative way instead of adding these fields to every

  • Issues using MS Access as a front-end to a MySQL database back-end? 2008-08-08

    Two users wanted to share the same database, originally written in MS Access, without conflicting with one another over a single MDB file. I moved the tables from a simple MS Access database to MySQL using its Migration Toolkit (which works well, by

  • What's your opinion on using UUIDs as database row identifiers, particularly in web apps? 2008-08-08

    I've always preferred to use long integers as primary keys in databases, for simplicity and (assumed) speed. But when using a REST or Rails-like URL scheme for object instances, I'd then end up with URLs like this: http://example.com/user/783 And the

  • How do you manage databases in development, test, and production? 2008-08-08

    I've had a hard time trying to find good examples of how to manage database schemas and data between development, test, and production servers. Here's our setup. Each developer has a virtual machine running our app and the MySQL database. It is their

  • Does running a SQL Server 2005 database in compatibility level 80 have a negative impact on performance? 2008-08-10

    Our software must be able to run on SQL Server 2000 and 2005. To simplify development, we're running our SQL Server 2005 databases in compatibility level 80. However, database performance seems slower on SQL 2005 than on SQL 2000 in some cases (we ha

  • What's your favourite way of interacting with databases from your programming language? 2008-08-11

    There are numerous ways to connect and interact with the database layer. In Java, for example, common usages are JDBC calls of raw SQL, object relational mappers, JDBCTemplate (Spring), stored procedures, etc. In your language, which option is your p

  • MySQL replication: if i don't specify any databases, will log_bin log EVERYTHING? 2008-08-11

    I'm setting up replication for a server which runs a bunch of databases (one per client) and plan on adding more all the time, on my.cnf, Instead of having: binlog-do-db = databasename 1 binlog-do-db = databasename 2 binlog-do-db = databasename 3 ...

  • any sample MySQL databases I can download? 2008-08-12

    I'm doing some inter-database operational research... e.g. synchronizing Oracle, MySQL, etc. Are there any nice MySQL databases that I can download, so that I can test some importing on real-world cases? I'm thinking of some open project that might h

  • Instrumenting Database Access 2008-08-12

    Jeff mentioned in one of the podcasts that one of the things he always does is put in instrumentation for database calls, so that he can tell what queries are causing slowness etc. This is something I've measured in the past using SQL Profiler, but I

  • Anyone know of an on-line free database? 2008-08-12

    I wrote an application that currently runs against a local instance of MySql. I would like to centralize the DB somewhere on the Net, and share my application. But, I'm cheap, and don't want to pay for it. Does anyone know of a free on-line relationa

  • Use for the phppgadmin Reports Database? 2008-08-12

    Phppgadmin comes with instructions for creating a reports database on the system for use with phppgadmin. The instructions describe how to set it up, but do not really give any indication of what its purpose is, and the phppgadmin site was not very h

  • Storing a file in a database as opposed to the file system? 2008-08-12

    Generally, how bad of a performance hit is storing a file in a database (specifically mssql) as opposed to the file system? I can't come up with a reason outside of application portability that I would want to store my files as varbinaries in SQL Ser

  • Default database IDs; system and user values 2008-08-13

    As part of our current database work, we are looking at a dealing with the process of updating databases. A point which has been brought up recurrently, is that of dealing with system vs. user values; in our project user and system vals are stored to

  • SQL Database documentation? 2008-08-13

    specifically, I use SQL Server 2005, but the solution might be brand independent. Need: You have 40 database tables, in some, you may have a column which is a integer values 1-9 representing some enum. Sure it makes sense in code, but not if you need

Copyright (C) pcaskme.com, All Rights Reserved.

processed in 1.837 (s). 13 q(s)