SwapCursor undefined when creating a CursorLoader - android

I am receiving a "swapCursor(Cursor) is undefined" error when creating a CursorLoader. I have imported the android.support.v4 (app.LoaderManager, app.LoaderManager.Loader, Content.CursorLoader, content.Loader). Not sure what I can do to correct this issue. please advise.
loader:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.app.ListFragment;
import android.support.v4.widget.CursorAdapter;
public class LoginList extends FragmentActivity implements OnClickListener,
AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> {
private ListView loginList;
private Button webLogin;
private SimpleCursorAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)findViewById(R.id.button3);
webLogin.setOnClickListener(this);
//Specify fileds to display in the list
String[] from = new String[] { ListProvider.COLUMN_NAME_SITE };
//Bind fields to listview
int[] to = new int[] {R.id.loginlist};
// Create CursorAdapter and set it to display
adapter = new SimpleCursorAdapter(this, R.layout.login_listview, null, from, to);
loginList.setAdapter(adapter);
getSupportLoaderManager().initLoader(0, null, this);
}
/*#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setEmptyText(getResources().getString(string.app_name));
rwgisterForContextMenu(getListView());
setHasOptionsMenu(true);
} */
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Selected ID :" + arg2, Toast.LENGTH_SHORT).show();
Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
Cursor clickedObject = (Cursor)loginList.getItemAtPosition(arg2);
Bundle loginBundle = new Bundle();
loginBundle.putString("clickedWebSite",((LoginDetails) clickedObject).getsName());
loginBundle.putString("clickedWebAddress",((LoginDetails) clickedObject).getwUrl());
loginBundle.putString("clickedUserName",((LoginDetails) clickedObject).getuName());
loginBundle.putString("clickedPassWord",((LoginDetails) clickedObject).getpWord());
loginBundle.putString("clickedNotes",((LoginDetails) clickedObject).getlNotes());
updateDeleteLoginInfo.putExtras(loginBundle);
startActivityForResult(updateDeleteLoginInfo, 0);
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
#Override
public Loader<Cursor> onCreateLoader(int ignored, final Bundle args) {
return new CursorLoader(this, ListProvider.CONTENT_URI, null, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor); /* swapCursor error: The method swapCursor(Cursor) is undefined for the type SimpleCursorAdapter */
}
#Override
public void onLoaderReset (Loader<Cursor> loader) {
adapter.swapCursor(null); /* swapCursor error: The method swapCursor(Cursor) is undefined for the type SimpleCursorAdapter */
}
}

Example on how to use changeCursor() with LoaderManager.LoaderCallbacks instead of swapCursor().
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(this, DB_table.CONTENT_URI, DB_table.PROJECTION,null,null,null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.changeCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
if you want to use the swapCursor() available in API 11 for older API's, remember to import the CursorAdapter from the support library.
import android.support.v4.widget.CursorAdapter;

In your onCreate() method you initialize your adapter passing the ListView as the second argument. This is incorrect, it should be the ID of a layout to instantiate for each item in the list:
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, from, to);
Other than that your code looks fine to me. I've compared it against working code of mine that used a ListFragment so I don't instantiate a UI but override the onActivityCreated(Bundle) method.
I did take the trouble to provide a projection to cut down the amount of data extracted from database by my ContentProvider, but passing null shouldn't be a problem.
But do check that you provide the "_id" primary key column as a long in your ContentProvier. To use ListView (and some of the other widgets) you have to have a Long based primary key, which I found really inconvenient as I already had a perfectly acceptable UUID as my primary key.

Related

How do i add onClick listener that would return the value of the clicked list from this code? (this is my first time coding andorid)

I've found this code from here
github
I've already created a Class with a method that would take the returned value from the list and retrieve appropriate value from database based on the value.
All i need right now is an onClick handler for this code that would return me a value of the clicked item on the list.
public class MainActivity extends ListActivity {
private Cursor employees;
private MyDatabase db;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
db = new MyDatabase(this);
employees = db.getDisease(); // you would not typically call this on the main thread
ListAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
employees,
new String[] {"FirstName"},
new int[] {android.R.id.text1});
getListView().setAdapter(adapter);
}
#Override
protected void onDestroy() {
super.onDestroy();
employees.close();
db.close();
}
}

Listview and data updating

I have a question.
I am programming a application to add records to a Content Provider.
The content provider is working perfectly.
My problem is when I tried to insert some data into the listview. It inserts, but I'm not able to see the data(Except that I restart the app).
I was calling notifydatasetchanged from the adapter but it didn't work.
public class MainActivity extends Activity implements
LoaderManager.LoaderCallbacks<Cursor> {
ListView listContacts;
ListView listView;
Button addContactButton;
MyAdapter adapter;
ContentValues values;
ContentResolver contentResolver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentResolver = getContentResolver();
listView = (ListView) findViewById(R.id.listView1);
values = new ContentValues();
getLoaderManager().initLoader(0, null, this);
addContactButton = (Button) findViewById(R.id.button1);
addContactButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final Dialog dialogForm = new Dialog(v.getContext());
dialogForm.setTitle("Add a new Address");
dialogForm.setContentView(R.layout.dialog);
dialogForm.show();
Button saveButton = (Button) dialogForm
.findViewById(R.id.saveButton);
final EditText addressEditText = (EditText) dialogForm
.findViewById(R.id.addressEditText);
saveButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
values.put(Contract.DATA, addressEditText.getText()
.toString());
contentResolver.insert(
Contract.CONTENT_URI, values);
values.clear();
dialogForm.dismiss();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
((MyAdapter)listView.getAdapter()).notifyDataSetChanged() ;
}
});
}
#Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new CursorLoader(this, Contract.CONTENT_URI, null, null, null,
null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter = new MyAdapter(this, R.layout.list_item, cursor, 0);
listView.setAdapter(adapter);
adapter.swapCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
}
Can someone give me a clue about this problem?
Also, I have another question. Is efficient the implementation of onLoadFinished method?
Greetings
You need to call restartLoader to refresh the data inside the listview.
http://developer.android.com/reference/android/app/LoaderManager.html
when you make changes to ContentProvider data, you must call getLoaderManager().restartLoader().It will discard any old data and onCreateLoader will be called again which will in turn fetch updated records and ListView will be updated.
Below is nice tutorial on Loaders.
http://www.grokkingandroid.com/using-loaders-in-android/

ListFragment doesn't update data from CursorLoader

I need to show some data from server. There are several fragments where items can be displayed, so it is not easy to mantain updates. I decided to cache data in DB and use ContentProvider to access it. But I have a strange issue.
Initially, there is no data in my database. I create CursorLoader and set CursorAdapter as adapter to ListFragment. Then I receive something from server and insert several records. I supposed Loader to be automatically notified about them and reload data. But nothing happens, and ListFragment stays empty.
The other strange thing related. I've wrote some code to add ActionBar menu for this fragment. In this situation it onCreateOptionsMenu is not called (despite of setHasOptionsMenu(true) in onCreate) and menu not added. When DB already has some data, it works normally.
It seems that something broken inside the Fragment, but there is nothing about this in logs. What do you think, what I am doing wrong?
Here is sample fragment, that works like this:
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.Menu;
import android.view.MenuInflater;
public class FeedFragment3 extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private static final int LOADER_ID = 1;
private SimpleCursorAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onResume() {
super.onResume();
getActivity().getActionBar().setTitle(R.string.feed_ab_title);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.feed, menu);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1, null,
new String[] {"title"},
new int[] {android.R.id.text1}
);
setListAdapter(mAdapter);
getActivity().getSupportLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), Consts.getFeedContentUri(), null, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.changeCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
}
Here is a part of ContentProvider. I suppose that calling notifyChange in insert and setNotificationUri in query make ContentProvider notified about changes. May be it is not enough?
public class FeedContentProvider extends ContentProvider {
...
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
DPLog.it(TAG, "Query: [%s]", uri);
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("feed");
qb.setProjectionMap(mProjectionMap);
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, null);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
DPLog.it(TAG, "insert: [%s]", uri);
String tableName = mTableNamesForCode.get(mUriMatcher.match(uri));
mDb.getWritableDatabase().insert(tableName, null, values);
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
...
}
Opening fragment in Activity:
private void openFeedFragment() {
mFeedFragment = new FeedFragment3();
showRootFragment(mFeedFragment);
updateFeed();
}
private void updateFeed() {
mApi.requestFeed(
new Response.Listener<FeedResponse>() {
#Override
public void onResponse(FeedResponse response) {
Uri uri = PostsContract.getFeedContentUri();
Set<Long> existingIds = getPostIds(uri);
ArrayList<ContentProviderOperation> operations = createMergeOperations();
try {
getContentResolver().applyBatch(PostsContract.AUTHORITY, operations);
} catch (RemoteException e) {
...
} catch (OperationApplicationException e) {
...
}
}
},
null
);
}
Logs when creating Fragment
03-21 19:12:35.041 22005-22344/com.app D/app.ContentProvider﹕ Cursor size: [0] 03-21 19:12:35.061 22005-22005/com.app V/app.checkpoint-checkpoint﹕ com.app.ui.fragment.FeedFragment3.onLoadFinished (FeedFragment3.java:60)
03-21 19:12:36.012 22005-22066/com.app D/app.API﹕ Request 'feed' finished
03-21 19:12:36.092 22005-22066/com.app D/dalvikvm﹕ GC_FOR_ALLOC freed 1417K, 11% free 12805K/14256K, paused 25ms, total 25ms
03-21 19:12:36.122 22005-22005/com.app I/app.ContentProvider﹕ Query: [content://com.app.content.posts/feed] (PostsContentProvider.java:59)
03-21 19:12:36.122 22005-22005/com.app D/app.ContentProvider﹕ Cursor size: [0] (PostsContentProvider.java:78)
03-21 19:12:36.142 22005-22005/com.app I/app.ContentProvider﹕ insert: [content://com.app.content.posts/feed] (PostsContentProvider.java:97)
03-21 19:12:36.262 22005-22005/com.app D/app.ContentProvider﹕ Inserted id: [1] (PostsContentProvider.java:102)
...
03-21 19:12:37.453 22005-22005/com.app D/app.ContentProvider﹕ Inserted id: [21] (PostsContentProvider.java:102)
03-21 19:12:37.453 22005-22348/com.app I/app.ContentProvider﹕ Query: [content://com.app.content.posts/feed] (PostsContentProvider.java:59)
03-21 19:12:37.453 22005-22348/com.app D/app.ContentProvider﹕ Cursor size: [21] (PostsContentProvider.java:78)
03-21 19:12:37.463 22005-22073/com.app I/app.ContentProvider﹕ Query: [content://com.app.content.posts/feed] (PostsContentProvider.java:59)
03-21 19:12:37.463 22005-22073/com.app D/app.ContentProvider﹕ Cursor size: [21] (PostsContentProvider.java:78)
03-21 19:12:37.463 22005-22005/com.app V/app.checkpoint-checkpoint﹕ com.app.ui.fragment.FeedFragment3.onLoadFinished (FeedFragment3.java:60)
in your code :-
use swapCursor(data) instead of changeCursor(data)
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), Consts.getFeedContentUri(), null, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
try it
for the first problem the error is the constructor of SimpleCursorAdapter that is deprecated and you must say to listen the changes like this:
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_1,
null,
new String[] {"title"},
new int[] {android.R.id.text1},
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER)
);
for the second you try this that works for me:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
[...]
}
in the end NOT use getActivity().getActionBar() but getSupportActionBar if you are using
import android.support.v4.app.ListFragment;
EDIT:
improve and fix your loader:
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
switch (cursorLoader.getId()) {
case LOADER_ID:
mAdapter.swapCursor(cursor);
break;
}
}
Not sure if this should make a difference, but use the fragment's LoaderManager instead of the activity's.
Replace
getActivity().getSupportLoaderManager().initLoader(LOADER_ID, null, this);
with
getLoaderManager().initLoader(LOADER_ID, null, this);

how to get value in textview in method onItemClickListener in android

This is the code of my main page:
package com.buanasoft.toko;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class f_penjualan extends Activity {
private long rowID;
private TextView nm_barangTv;
private TextView hargaTv;
private TextView h_jualTv;
private TextView satuanTv;
private TextView stokTv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.f_penjualan);
setUpViews();
Bundle extras = getIntent().getExtras();
rowID = extras.getLong(f_data.ROW_ID);
Button go = (Button)findViewById(R.id.btn_pilih);
Intent i = this.getIntent();
go.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i = new Intent(getApplicationContext(), daftar_barang.class);
startActivity(i);
}
});
}
private void setUpViews() {
nm_barangTv = (TextView) findViewById(R.id.namaBarangText);
hargaTv = (TextView) findViewById(R.id.hargaBarangText);
h_jualTv = (TextView) findViewById(R.id.hargaJualText);
satuanTv = (TextView) findViewById(R.id.satuanText);
stokTv = (TextView) findViewById(R.id.stokText);
}
#Override
protected void onResume()
{
super.onResume();
new LoadBarang().execute(rowID);
}
private class LoadBarang extends AsyncTask<Long, Object, Cursor>
{
DBCon_barang dbCon_barang = new DBCon_barang(f_penjualan.this);
#Override
protected Cursor doInBackground(Long... params)
{
dbCon_barang.open();
return dbCon_barang.getOneBarang(params[0]);
}
#Override
protected void onPostExecute(Cursor result)
{
super.onPostExecute(result);
result.moveToFirst();
// get the column index for each data item
int nm_barangIndex = result.getColumnIndex("nm_barang");
int hargaIndex = result.getColumnIndex("harga");
int h_jualIndex = result.getColumnIndex("h_jual");
int satuanIndex = result.getColumnIndex("satuan");
int stokIndex = result.getColumnIndex("stok");
nm_barangTv.setText(result.getString(nm_barangIndex));
hargaTv.setText(result.getString(hargaIndex));
h_jualTv.setText(result.getString(h_jualIndex));
satuanTv.setText(result.getString(satuanIndex));
stokTv.setText(result.getString(stokIndex));
result.close();
dbCon_barang.close();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.det_data_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.editItem:
Intent addEditBarang =
new Intent(this, AddEditBarang.class);
addEditBarang.putExtra(f_data.ROW_ID, rowID);
addEditBarang.putExtra("nm_barang", nm_barangTv.getText());
addEditBarang.putExtra("harga", hargaTv.getText());
addEditBarang.putExtra("h_jual", h_jualTv.getText());
addEditBarang.putExtra("satuan", satuanTv.getText());
addEditBarang.putExtra("stok", stokTv.getText());
startActivity(addEditBarang);
return true;
case R.id.deleteItem:
deleteBarang();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void deleteBarang()
{
AlertDialog.Builder alert = new AlertDialog.Builder(f_penjualan.this);
alert.setTitle(R.string.confirmTitle);
alert.setMessage(R.string.confirmMessage);
alert.setPositiveButton(R.string.delete_btn,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int button)
{
final DBCon_barang dbCon_barang =
new DBCon_barang (f_penjualan.this);
AsyncTask<Long, Object, Object> deleteTask =
new AsyncTask<Long, Object, Object>()
{
#Override
protected Object doInBackground(Long... params)
{
dbCon_barang.deleteBarang(params[0]);
return null;
}
#Override
protected void onPostExecute(Object result)
{
finish();
}
};
deleteTask.execute(new Long[] { rowID });
}
}
);
alert.setNegativeButton(R.string.cancel_btn, null).show();
}
}
and this is the code from my second activity
public class daftar_barang extends ListActivity {
public static final String ROW_ID = "row_id";
private ListView conListView;
private CursorAdapter conAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
////script untuk memampilkan daftar barang & menu
conListView=getListView();
conListView.setOnItemClickListener(viewConListener);
// mengisi value di TextView
String[] from = new String[] { "nm_barang" };
int[] to = new int[] { R.id.daftar_barang };
conAdapter = new SimpleCursorAdapter(daftar_barang.this, R.layout.daftar_barang, null, from, to);
setListAdapter(conAdapter); // set adapter
}
#Override
protected void onResume()
{
super.onResume();
new GetData().execute((Object[]) null);
}
#Override
protected void onStop()
{
Cursor cursor = conAdapter.getCursor();
if (cursor != null)
cursor.deactivate();
conAdapter.changeCursor(null);
super.onStop();
}
private class GetData extends AsyncTask<Object, Object, Cursor>
{
DBCon_barang dbConnector = new DBCon_barang(daftar_barang.this);
#Override
protected Cursor doInBackground(Object... params)
{
dbConnector.open();
return dbConnector.getAllBarang();
}
#Override
protected void onPostExecute(Cursor result)
{
conAdapter.changeCursor(result); // set the adapter's Cursor
dbConnector.close();
}
}
//fungsi untuk melihat detail barang
OnItemClickListener viewConListener = new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)
{
Intent viewCon = new Intent(daftar_barang.this,f_penjualan.class);
viewCon.putExtra(ROW_ID, arg3);
startActivity(viewCon);
}
};
}
I want to display the data item from my second activity to first activity.
So by the time I get into the second activity and I click on one of the data in the second activity, he will be on show to the first activity.
There is no error warning, but after building my application some errors occurred when I open the activity.
Your problem is in onCreate() of the first activity. You have this code:
Bundle extras = getIntent().getExtras();
rowID = extras.getLong(f_data.ROW_ID);
When your activity is first launched it won't contain any extras, so the call to getIntent().getExtras() will return null. The next statement will then throw a NullPointerException. You need to check for extras == null before calling getLong() on it.

Android - onLoadFinished not called

I am facing an issue with Loader.
I have an Activity, which displays list of records retrieved from local DB. When the activity starts, records are automatically loaded via LoaderManager.initLoader() method.
There is also possibility to manually refresh the list via refresh button in ActionBarSherlock. However, after finishing another activity which adds a record to DB, onLoadFinished is not called.
I am using SimpleCursorLoader and here is code snippet from the activity:
#Override
public void onStart() {
...
getSupportLoaderManager().initLoader(0, null, this);
}
#Override
public void onPause() {
...
getSupportLoaderManager().destroyLoader(0);
}
public void refreshRecords() {
getSupportLoaderManager().restartLoader(0, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, final Bundle args) {
Loader<Cursor> l = new SimpleCursorLoader(this) {
#Override
public Cursor loadInBackground() {
return recordDAO.getCursor();
}
};
l.forceLoad();
return l;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
// updateUI
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
The issue is that after finishing the other activity, onLoaderCreate is called, but onLoaderFinished is not called.
after some debugging, I've found that SimpleCursorAdapter.deliverResults() is also called, bud ends up on .. if (isReset()) { ..
Am I missing something? How to force the reload of data?
Thank you in advance
I have finally found the solution to this problem thanks to the discussion on
https://groups.google.com/forum/#!topic/android-developers/DbKL6PVyhLI
public static <T> void initLoader(final int loaderId, final Bundle args, final LoaderCallbacks<T> callbacks,
final LoaderManager loaderManager) {
final Loader<T> loader = loaderManager.getLoader(loaderId);
if (loader != null && loader.isReset()) {
loaderManager.restartLoader(loaderId, args, callbacks);
} else {
loaderManager.initLoader(loaderId, args, callbacks);
}
}
In addition as of support library 28 make sure that you don't call initLoader from within Fragment.onCreate(). As the updated documentation states
You typically initialize a Loader within the activity's onCreate() method, or within the fragment's onActivityCreated() method.
see https://developer.android.com/guide/components/loaders
RaB solution dont work for me
My worked Solution, was always destroy Loader before restart
Loader<Cursor> loader = mLoaderManager.getLoader(mKeyLoader);
if (loader != null)
{
mLoaderManager.destroyLoader(mKeyLoader);
}
mLoaderManager.restartLoader(mKeyLoader, args, this);
In addition to RaB's answer, if you are using a custom Loader, make sure that if you call super if you overwrite deliverResult():
#Override
public void deliverResult(D data) {
super.deliverResult(data); // <--onLoadFinished() will not be called if you don't call this
...
}
fwiw, I had a similar problem from attempting to immediately restart the loader a second time, before the first onLoadFinished was called, resulting in neither being called.
this worked for me:
if( loader == null )
loader = loaderMngr.initLoader(
0, null, myLoaderCallbacks
);
else if( loader.isAbandoned() )
return;
else
loaderMngr.restartLoader(
0, null, myLoaderCallbacks
);
Check the support library.Use this import android.support.v4.app. Don't use android.app.loadermanager.
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
Initialize part
LoaderManager mLoaderManager=getSupportLoaderManager();
LoaderManager.LoaderCallbacks<Cursor> mCursorLoaderCallbacks=new LoaderManager.LoaderCallbacks<Cursor>() {
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle cursor) {
return new CursorLoader(getActivity(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, COLUMNS_OF_INTEREST, null, null,
MediaStore.Video.Media.DATE_ADDED + " DESC");
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
mLoaderManager.initLoader(URL_LOADER_EXTERNAL, null, mCursorLoaderCallbacks);

Categories

Resources