Im trying to make use of the LoaderManager and the CursorLoader to read the phone numbers of contacts. I'm able to read the contact's display name but Im not sure how to read the phone numbers. Any guidance would be much appreciated.
// These are the Contacts rows that we will retrieve.
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
Contacts._ID, Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER };
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
// If non-null, this is the current filter the user has provided.
String mCurFilter;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("No phone numbers");
// Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null, new String[] {
Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER },
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Log.i("FragmentComplexList", "Item clicked: " + id);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(mCurFilter));
} else {
baseUri = Contacts.CONTENT_URI;
}
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
Try this.. this worked for me!
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
// If non-null, this is the current filter the user has provided.
String mCurFilter;
#Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("No phone numbers");
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_1, null,
new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER, },
new int[] { android.R.id.text1}, 0);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
#Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Place an action bar item for searching.
MenuItem item = menu.add("Search");
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
View searchView = SearchViewCompat.newSearchView(getActivity());
if (searchView != null) {
SearchViewCompat.setOnQueryTextListener(searchView,
new OnQueryTextListenerCompat() {
#Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
return true;
}
});
item.setActionView(searchView);
}
}
#Override public void onListItemClick(ListView l, View v, int position, long id) {
// Insert desired behavior here.
Log.i("FragmentComplexList", "Item clicked: " + id);
}
// These are the Contacts rows that we will retrieve.
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(mCurFilter));
} else {
baseUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
}
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
String select = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ ContactsContract.Contacts.DISPLAY_NAME + " != '' )" + "AND ("+ContactsContract.Contacts.HAS_PHONE_NUMBER +" != '0'"+"))";
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, null, null,
null + " COLLATE LOCALIZED ASC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
}
Related
I want to display the Contact List using Fragment. The number will show on toast when the user selects names from the list.The list will show only name.How can I get the numbers form contact. I went through the android developer training for retrieving a contact list, but the tutorial is incomplete and even downloading the sample code doesn't help because the sample code is for more advanced contact list manipulation (search, etc.)
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Context context = getActivity();
int layout = android.R.layout.simple_list_item_1;
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-requery! Loader requeries.
mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
final ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Toast.makeText(getActivity(), " Clicked!"
, Toast.LENGTH_SHORT).show();
}
});
// each time we are started use our listadapter
setListAdapter(mAdapter);
// and tell loader manager to start loading
getLoaderManager().initLoader(0, null, this);
}
#SuppressLint("InlinedApi")
private static final String SELECTION = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?" : Contacts.DISPLAY_NAME + " LIKE ?";
private String mSearchString;
private String[] mSelectionArgs = { mSearchString };
private static final String[] PROJECTION =
{
Contacts._ID,
Contacts.LOOKUP_KEY,
Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
Contacts.DISPLAY_NAME_PRIMARY :
Contacts.DISPLAY_NAME
};
private static final String[] FROM = { Contacts.DISPLAY_NAME_PRIMARY };
private static final int[] TO = { android.R.id.text1 };
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
Uri contentUri = Contacts.CONTENT_URI;
return new CursorLoader(getActivity(), Contacts.CONTENT_URI, PROJECTION, null, null, Contacts.DISPLAY_NAME+" ASC");
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
mAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
mAdapter.swapCursor(null);
}
How can I get the numbers form contact
I'd start with editing your PROJECTION array and adding HAS_PHONE_NUMBER column to not proceed if there's no phone number associated.
If there's is, then using your contact's ID you can do something like this (note the type constrain, so edit according to your needs):
Cursor cursorPhone = getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[]{ ContactsContract.CommonDataKinds.Phone.NUMBER },
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? AND " +
ContactsContract.CommonDataKinds.Phone.TYPE + " = " +
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,
new String[]{ contactId },
null);
if (cursorPhone.moveToFirst()) {
contactNumber = cursorPhone.getString(cursorPhone
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
cursorPhone.close();
Right now, my app filters the data in a listview when somethings is entered into the editText, but it can only filter by one thing at a time. I want it to be able to filter by more than value. For example, if someone types in "chicken" it should filter the recipes by the word 'chicken'. But, if someone then types in "dinner", I want it to filter the recipes by both "chicken" and "dinner." Eventually, I want to make it so those values appear as checkboxes above the listview so they can be easily removed.
I can't figure out how to do this. I played around with loops at first but didn't really get anywhere.
public class SearchActivity extends NavDrawerActivity {
private DBHandler dbHelper;
private SimpleCursorAdapter dataAdapter;
ArrayList<String> filters = new ArrayList<String>();
//String[] filters;
FrameLayout frameLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main_activity3);
frameLayout = (FrameLayout) findViewById(R.id.activity_frame);
// inflate the custom activity layout
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = layoutInflater.inflate(R.layout.activity_main_activity3, null, false);
// add the custom layout of this activity to frame layout.
frameLayout.addView(activityView);
dbHelper = new DBHandler(this, null, null, 1);
//dbHelper.open();
//Clean all data
dbHelper.deleteAllRecipes();
//Add some data
dbHelper.insertSomeRecipes();
//Generate ListView from SQLite Database
displayListView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
private void displayListView() {
final Cursor cursor = dbHelper.fetchAllRecipes();
// The desired columns to be bound
String[] columns = new String[]{
//DBHandler.COLUMN_CODE,
DBHandler.COLUMN_NAME,
DBHandler.COLUMN_TYPE,
DBHandler.COLUMN_INGRED
};
// the XML defined views which the data will be bound to
int[] to = new int[]{
//R.id.code,
R.id.name,
R.id.type,
R.id.ingredient,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.recipeinfo,
cursor,
columns,
to,
0);
ListView listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
String recipeName = cursor.getString(cursor.getColumnIndexOrThrow("name"));
Intent n = new Intent(getApplicationContext(), RecipeActivity.class);
//n.putExtra("position", position);
n.putExtra("recipeName", recipeName);
startActivity(n);
}
});
//final GridView gridView = (GridView)findViewById(R.id.gridView);
final TextView tv = (TextView)findViewById(R.id.textView14);
final EditText myFilter = (EditText) findViewById(R.id.myFilter);
myFilter.setImeActionLabel("Filter",1);
myFilter.setPrivateImeOptions("actionUnspecified");
myFilter.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
if (id == 1 || id == EditorInfo.IME_NULL) {
String filter = textView.getText().toString();
dataAdapter.getFilter().filter(filter);
filters.add(filter);
tv.append(filter);
myFilter.setText("");
}
return false;
}
});
dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return dbHelper.fetchRecipesByName(constraint.toString());
}
});
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Then you start a new Activity via Intent
Intent intent = new Intent();
intent.setClass(this, RecipeActivity.class);
intent.putExtra("position", position);
// Or / And
intent.putExtra("id", id);
startActivity(intent);
}
}
fetchRecipesByName in DBHandler
public Cursor fetchRecipesByName(String inputText) throws SQLException {
SQLiteDatabase mDb = this.getWritableDatabase();
Log.w(TAG, inputText);
Cursor mCursor = null;
if (inputText == null || inputText.length () == 0) {
mCursor = mDb.query(SQLITE_TABLE, new String[] {COLUMN_ROWID,
COLUMN_NAME, COLUMN_TYPE, COLUMN_INGRED, COLUMN_IMGPATH},
null, null, null, null, null);
}
else {
mCursor = mDb.query(true, SQLITE_TABLE, new String[] {COLUMN_ROWID,
COLUMN_NAME, COLUMN_TYPE, COLUMN_INGRED, COLUMN_IMGPATH},
COLUMN_NAME + " like '%" + inputText + "%'" + " or " +
COLUMN_TYPE + " like '%" + inputText + "%'" + " or " +
COLUMN_INGRED + " like '%" + inputText + "%'",
null, null, null, null, null);
}
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
What is the implementation of dbHelper.fetchReccipesByName()? I think, as of now, it queries the table only by one thing. You should change its logic and implement your complex need in this method (obviously, it should be an SQL query execution).
As a best practice, you should call listView.setFilterText() instead of dataAdapter.getFilter().filter(), because this method is supposed to run in secondary thread for the reason that DB queries are time consuming. If you call listView.setFilterText(), the framework will take care of threading and calls filter.filter() in secondary thread.
And finally, since you are searching by more than one keyword, but setFilterText() accepts only one CharSequence param, you should encode somehow many keywords into single String (say comma separated). And while querying you could decode the constraint to get the keywords.
I want to have a ListView of my contacts.
I use Google sample code.
The problem is that I get the same contacts over and over again:
Jim
Jim
Jim
Jim
Jim
Anna
Anna
Anna
Anna
...
How can I get a DISTINCT list of my contacts?
public class ContactsListView extends ListActivity
implements LoaderManager.LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter;
static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME};
static final String SELECTION = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '"
+ ("1") + "'";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a progress bar to display while the list loads
ProgressBar progressBar = new ProgressBar(this);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,Gravity.CENTER));
progressBar.setIndeterminate(true);
getListView().setEmptyView(progressBar);
// Must add the progress bar to the root of the layout
ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
root.addView(progressBar);
// For the cursor adapter, specify which columns go into which views
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1
// Create an empty adapter we will use to display the loaded data.
// We pass null for the cursor, then update it in onLoadFinished()
mAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, null,
fromColumns, toViews, 0);
setListAdapter(mAdapter);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
// Called when a new Loader needs to be created
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
PROJECTION, SELECTION, null, ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC");
}
// Called when a previously created loader has finished loading
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
}
// Called when a previously created loader is reset, making the data unavailable
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id)
{
// String itemValue = (String) l.getItemAtPosition(position);
}
}
In your line with String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};, instead of
ContactsContract.Data.DISPLAY_NAME
try
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
In the documentation you can read that Data are entries representing any number or email address or whatever, while Contacts are entries representing one person.
try this code
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '"
+ ("1") + "'";
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";
cur = context.getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, projection, selection
+ " AND " + ContactsContract.Contacts.HAS_PHONE_NUMBER
+ "=1", null, sortOrder);// this query only return contacts which had phone number and not duplicated
for your code))
// Called when a new Loader needs to be created
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
projection, selection
+ " AND " + ContactsContract.Contacts.HAS_PHONE_NUMBER
+ "=1", null, sortOrder);
}
Use set instead of List. Set holds only unique elements, so duplicate elements are not present in resultant collection.
I want to get DISPLAY_NAME & COMAPNY name of all contacts the same time by using cursorloader. And I have already get DISPLAY NAME of them.
My problem is that I do not know how to get COMPANY name the same time with DISPLAY_NAME!
Could you show me the way to solve my question. Here is my code.
public class MainActivity extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor>{
SimpleCursorAdapter mAdapter;
LoaderManager loadermanager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadermanager = getLoaderManager();
String[] fromColumns = {ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME};
int[] toViews = {R.id.contactId,
R.id.contactName};
mAdapter = new SimpleCursorAdapter(this,
R.layout.view_contact_entry, null,
fromColumns, toViews, 0);
setListAdapter(mAdapter);
loadermanager.initLoader(1, null, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.Contacts.DISPLAY_NAME};
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'";
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return new CursorLoader(this, ContactsContract.Contacts.CONTENT_URI,
projection, selection, null, sortOrder);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if(mAdapter!=null && cursor!=null)
mAdapter.swapCursor(cursor);
else
Log.v("MAIN","OnLoadFinished: mAdapter is null");
}
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
try {
Cursor cs = (Cursor)l.getItemAtPosition(position);
Intent objIndent = new Intent(getApplicationContext(),DetailContact.class);
objIndent.putExtra("contactId", cs.getString(0));
objIndent.putExtra("contactName", cs.getString(1));
startActivity(objIndent);
} catch (Exception e) {
Log.e("ERROR: ", e.getMessage());
}
}
}
I think you need to look at querying against the ContactsContract.Data
There is an example of joining and pulling in additional data from the contact in the docs
along with this special constant ContactsContract.CommonDataKinds.Organization.COMPANY
I want to show the items queried from database in the listview with SimpleCursorAdapter.
For example, there may be 20,000 items in the database. I want to just load 100 items(_id : 1-100) queried instead of load all items, when scrolling in the end of listview, load another 100 items(_id : 101-200) queried, how to achieve it? Any suggestion is welcome, thanks.
Relative codes are as follows:
protected void onCreate(Bundle savedInstanceState) {
mCursor = managedQuery(CONTENT_URI, PROJECTION, null, null, "_id DESC");
mAdapter = new SimpleCursorAdapter(this,R.layout.list_content, mCursor, keys, values);
setListAdapter(mAdapter);
}
In my defined listview, i want to load more items by query database.
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
int lastItem = firstVisibleItem + visibleItemCount - 1;
if (mListAdapter != null) {
if ((lastItem == mListAdapter.getCount()-1) && (mRefreshState != REFRESHING)) {
mFooterView.setVisibility(View.VISIBLE);
mRefreshState = REFRESHING;
new Handler().postDelayed(new Runnable() {
public void run() {
//execute the task , i want to load more items by query database
RefreshListView(LOADING_STORED_INFO);
}
}, DEFAULT_DELAY_TIMER);
}
}
}
In the AsyncTask loading data, i do the query operation.
protected Integer doInBackground(Integer... params)
{
Uri uri = ContentUris.withAppendedId(CONTENT_URI, mCursor.getInt(0)-1);
cursor = managedQuery(uri, PROJECTION, null, null, "_id DESC");
return (0 == params[0]) ? 1 : 0;
}
#Override
protected void onPostExecute(Integer result)
{
mAdapter.changeCursor(cursor);//is this OK?
mAdapter.notifyDataSetChanged();
/*
if (1 == result)
{
mListView.setSelection(1);
}
else
{
mListView.setSelection(mCount-1);
}*/
// Call onRefreshComplete when the list has been refreshed.
mListView.onRefreshComplete(result);
super.onPostExecute(result);
}
Use the LIMIT statement in the SQL query in this way:
SELECT your_column FROM your_table ORDER BY your_order LIMIT limit_skip, limit_count
Then you can use a OnScrollListener to retrieve the index of the first visible cell and the number of visible cells so you can increment limit_skip and limit_count coherently.
Instead of the generic AsyncTask use a CursorLoader and implement LoaderManager.LoaderCallbacks<Cursor> as follow:
public Loader<Cursor> onCreateLoader(int id, Bundle args){
String orderBy = "_id DESC"
if(args != null){
orderBy += " LIMIT " + args.getInt("LIMIT_SKIP") + "," + args.getInt("LIMIT_COUNT");
}
return new CursorLoader(this /*context*/, CONTENT_URI, PROJECTION, null, null, orderBy);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data){
listAdapter.swapCursor(data);
}
public void onLoaderReset(Loader<Cursor> loader){
listAdapter.swapCursor(null);
}
Then, in onCreate(), pass null as cursor to new SimpleCursorAdapter() and create the CursorLoader in this way:
getLoaderManager().initLoader(0, null, this /*LoaderCallbacks<Cursor>*/);
Then, in onScroll(), reset everytime the loader in this way:
Bundle args = new Bundle();
args.putInt("LIMIT_SKIP", limit_skip_value);
args.putInt("LIMIT_COUNT", limit_count_value);
getLoaderManager().restartLoader(0, args, this /*LoaderCallbacks<Cursor>*/);