I have a ListFragment which displays a list of items obtained using a CursorLoader and a CursorAdapter as per the standard way of handling views of lists. This in itself is working fine,however I'm unsure as to how to use the same pattern to display the detailed view of a selected item.
A previous StackOverflow question discussed this but neither of the solutions suggested seem to me to be optimal. Using a ListView with a single item seems like overkill and wasteful of resources, whereas carrying out the work directly in the activity seems to be overloading the activity with data access and UI functionality. It also loses the ability to keep data in sync between the activity and the underlying storage.
Is there some middle ground that retains the split between loader, activity and adapter but for a single item rather than a list?
You can do without the Adapter and the ListView.
The CursorLoader returns you a Cursor. You can access the cursor without passing it to an adapter.
Just make sure the Cursor contains at least your one row.
if (cursor != null && cursor.moveToFirst()) {
// do whatever, ie String myString=cursor.getString(0)
// in case you fetch a string as the first element of your projection
}
Related
I've been attempting to implement drag and drop features into my notes app using ItemTouchHelper however I am struggling to figure out how to get it to work with cursors. I am currently retrieving stored note data from the database using a cursor loader and a content provider, and the adapter receives it's data from the returned cursor as shown.
public void onBindViewHolder(RecyclerViewAdapter.MyViewHolder holder, int position) {
mCursor.moveToPosition(position);
String title = mCursor.getString(mCursor.getColumnIndex(NotesContract.COL_TITLE));
String body = mCursor.getString(mCursor.getColumnIndex(NotesContract.COL_BODY));
holder.titleText.setText(title);
holder.bodyText.setText(body);
}
The problem I am having is that I don't know how I would keep track of the position of the moved items in the list when I drag and drop them. I can't change the order of the rows in the cursor. I have only seen examples where the data source for the adapter is a List. I have considered copying my cursor data into a list of Note objects, so that I could rearrange them to reflect the changes made by dragging and dropping, but this seems to defeat all you gain by using cursors and cursor loader. Also when cursor loader finishes loading it will return a new cursor with all the results in the original order again and populate the adapter accordingly, so any changes made to the order if my new List would be lost.
Does anyone know how to do this or am I going about this entirely the wrong way using cursors and a loader? Any help would be much appreciated. Thanks!
I have done this by adding a column named sort_order in the table to keep track of the sort order. When you drag and drop you update the sort_order in the onMove method in ItemTouchHelper.SimpleCallback.
A good tutorial how to implement drag and drop and swipe to dismiss you can find here
What exactly do you need that cursor for? If you have any specific question just add a comment. I worked a lot with this features!
I wrote my own CursorAdapter for RecyclerView like following link: https://gist.github.com/skyfishjy/443b7448f59be978bc59
Then I found whenever I change something in database and want to show it in RecyclerView, I need to create a new Cursor by db.query() and use CursorAdpater's changeCursor(). Since query() will scan all rows in database, the RecyclerView will refresh slowly when data amount is big even I insert only one row into database.
Besides, as we all know, RecyclerView provides notifyItemInserted/Removed(position) for developers so that the RecyclerView can refresh partly, which is useful and beneficial to memory/time. However, when I use CursorAdapter, I don't know when and how I can use these methods because changing cursor isn't adding something directly to dataset binding with RecyclerView but refreshing all items in fact.
So are there any better ways to show data from database in RecyclerView and use RecyclerView's improving method to show variety of database?
I can tell you what i've done...
A. Loaded a cursor using Loader.
B. Copied the cursor into arraylist that is attached to the adapter (the cursor isnt attached to the adapter directly), close the cursor. Works well if there isnt a lot of data - if there is a lot rows then i would have load some of it to the arraylist and then when the user would scroll down i would query again and load from the last row of the array.
C. When the user would like to delete or add something i would do the operation on arrayList first (UI thread) notifiyItemChanged and then change the db (Back thread)
Hope i helped.
I have a RecyclerView with an RecyclerView.Adapter whose backing data is coming from a Cursor via a Loader. The data contains two types of items: A and B returned via an UNION ALL. getItemViewType returns different ints for each (see note below). The A and B entities are from different SQLite database tables, and both theirs _id start from 1, so it's very like that there'll be a B whose _id is the same as an existing A and vice versa.
Is it safe to set setHasStableIds(true) on the above adapter?
It it possible that a weird case might happen when the cursor has both As and Bs with the same ID and an animation or recycle goes wrong?
Note:
All the other parts of the Adapter is pretty standard: getItemViewType is implemented by returning R.layout.a_view or R.layout.b_view. There are also separate ViewHolder subclasses for each type created in onCreateViewHolder with a switch on itemViewType.
All items are displayed correctly and even animate when I go away to another activity, modify some data and then press the back button (thanks to Loaders I guess).
GreenDAO.
Which there is a simple way to display all the records from a Entity in the ListView, and is supported with the auto-update the list.
Perhaps Lazylist class? how to use it?
Have a look here. I'm using an adapter like this (including a ViewHolder-Pattern to reuse the Views inside the ListView) as well and it is fast even for a lot of records. But this won't be usable if you need auto-update-functionality.
Here are some information about LasyList to explain why:
Get LazyList using Query.listLazy():
This will not show new inserted records (or stop deleted records from displaying) automatically, since the records are cached in memory.
Thus updates won't be visible, because records are not queried twice.
Get LazyList using Query.listLazyUncached():
Updates of already existing records may be visible, but only if the records updated are currently not displayed.
Also you should be careful because I think inserting or deleting records may break this list.
To get inserts and deletes into the list you will have to refresh the underlying LazyList and call notifyDataSetChanged().
I'm using this in my Adapter:
public void setLazyList(LazyList<T> list) {
if (list != lazyList) {
lazyList.close();
lazyList = list;
this.dataValid = lazyList != null;
notifyDataSetChanged();
}
}
By the way: If you are using LazyList:
Don't forget to close LazyLists if you are not using them any more!
I am new to Android and am trying to get my header round the SimpleCursorAdapter and CursorLoader classes. From my understanding, all of the examples that I have seen use these two classes to load data into a ListView in a background thread (to not block the UI).
I am OK with this and have used this general approach with my own list of items, however I now want to be able to click on an item in the list and get the full information for the item. Is it usual practice to use SimpleCursorAdapter and CursorLoader to retrieve the details for a single item? or are they just meant for lists?.
Thanks.
They are not meant for lists only. You can - and should - use them in detail views (activities) as well.
I've sketched a possible way to do so on my blog:
http://www.grokkingandroid.com/using-loaders-in-android/
Think of Adapters as a layer of abstraction between your data (Cursor) and whatever you attach that Adapter to (ListView for example). This way, you have a common interface between your data (Cursor, ArrayList, whatever) and the View you display that data on (ListView, TableView, etc.), this is helpful because if you later find that you want to access your data through an ArrayList rather than a Cursor, then you simply swap out the adapter with a different one and you're ready.
Now considering your question, Adapters give an abstract access to information, therefore you can "ask" it for what information is stored and where. You could attach an OnItemClickListener to your ListView and then access your data from there.