Fairly noobish and my first post here. I have an app that is working fine in 2.3.3 using a custom baseadapter to populate a listview. The problem is that I'm using startManagingCursor and requery which is deprecated in Android 3/4.
I'm using sqlite and a database adapter which holds all my queries and a private method to pass parameters from the activity. You can update the list by long pressing an item or clicking on an item to open it in a new activity and when you return the list updates successfully.
I understand that we shouldn't be running these types of operations on the main UI but I'm having trouble figuring out cursorloader and do I even need it? Should I be using something else like asynctask to run on a different thread. I'm just not understanding how this all fits together and any help in the right direction would be appreciated. Thanks.
Here's a SMALL sample of what I think the most relevant code would be from MyActivity
public class MyActivity extends ListActivity {
private MyDBAdapter dbAdapter;
private MyCursorAdapter mCursorAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
this.dbAdapter = new MyDBAdapter(this);
this.dbAdapter.open();
queryParams = getQueryParams();
queryDB(queryParams);
}
private void queryDB(String qParams) {
Cursor c = this.dbAdapter.fetchQuery(qParams);
startManagingCursor(c);
this.mCursorAdapter = new MyCursorAdapter(this, c);
setListAdapter(this.mCursorAdapter);
this.mCursorAdapter.changeCursor(c);
}
public void updateStatus(long paramLong, int paramInt) {
Cursor c = this.dbAdapter.updateDBStatus(paramLong, paramInt);
startManagingCursor(c);
this.mCursorAdapter.changeCursor(c);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (this.dbAdapter != null) {
this.dbAdapter.close();
}
}
}
and the CursorAdapter
public class MyCursorAdapter extends CursorAdapter {
public MyCursorAdapter(Context cxt, Cursor cur, int flags) {
super(cxt, cur);
mContext = cxt;
mLayoutInflater = LayoutInflater.from(cxt);
}
@Override
public View newView(Context cxt, Cursor cur, ViewGroup parent) {
View vw = mLayoutInflater.inflate(LAYOUT_ID, parent, false);
return vw;
}
@Override
public void bindView(View vw, Context cxt, Cursor cur) {
int id = cur.getInt(cur.getColumnIndexOrThrow("_id"));
String name = cur.getString(cur.getColumnIndexOrThrow("name"));
int completed = cur.getInt(cur.getColumnIndexOrThrow("completed"));
TextView tv = (TextView) vw.findViewById(R.id.name);
if(completed == 1) {
tv.setTextColor(0x7fffffff);
} else {
tv.setTextColor(0xffffffff);
}
}
}
================ EDIT ==================
I ended up removing startManagingCursor() and requery() and added import android.support.v4.widget.CursorAdapter from the compatibility package. Since I had multiple calls from different locations, I made a private Cursor mCursor and used this.mCursorAdapter.changeCursor(mCursor) to update it.
Now this pretty much works except:
- You really shouldn't be doing this as it still runs on the main UI
- Closing the cursor depends on how the app is setup
In my case, I can't close the cursor or else my listview would be empty. Closing it in the onDestroy() isn't guaranteed to run, and closing it in the onBackPressed() doesn't work since you can click on a list item which opens a new activity with a new cursor. And when someone clicks on a list item and then clicks the back button, the list should be in the same spot so closing onStop() (and opening in onStart()) isn't the answer either. I also tried a public static cursor across all activities too but that also had problems. One other thing that I did not try was to load the cursor information into memory at once and then close it immediately, but that seems less than ideal.
I really like the idea of the CursorLoader except that it only accepts a URI and you need a content provider and it doesn't accept rawQuery(). I have thousands of items in my db and a hundred different types of query calls with my database adapter and it seems like a big pain to change all that over. I think the CursorLoader is the best way to go but I'm disappointed with the way android implemented it.
I also saw CursorLoader usage without ContentProvider which someone wrote that uses AsyncTaskLoader so you won't need a ContentProvider. This might be my best bet right now but someone else pointed out that there is no mechanism to refresh on data changes. I will have to look into it and see.