Loader不更新屏幕上的列表。只有当我按下按钮并调用sampleLoader.onContentChanged()
时,列表才会更新。他们的广播接收器也存在一些问题。当我第一次更改配置时,它会在下面给出此错误。并且还会在活动重新启动时更新配置更改。但是如果保持活动打开服务添加的数据,则在后台dosn中更新列表。
代码:实施LoaderCallback的主要活动
public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<List<DemoItem>>,ServiceCallbacks {
private static final String TAG = "MainActivityFragment";
private static final int LOADER_ID = 1;
Context context;
private UpdateServices myService;
private boolean bound = false;
MySQLiteHelper m;
SampleLoader sampleLoader;
CustomAdapter customAdapter;
ListView mList;
ArrayList<DemoItem> allList;
Button b1,b2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* This condition check saved instance if any and assign it
*/
/*if (savedInstanceState != null) {
sampleLoader = (SampleLoader) savedInstanceState.getSerializable("ObjectA");
// check mObjectA == mObjectA.getObjectBList().get(0).getParent();
}*/
b1=(Button)findViewById(R.id.button);
b2=(Button)findViewById(R.id.button1);
m = new MySQLiteHelper(this);
/**
* This method initialize the Loader
*/
sampleLoader = (SampleLoader) getLoaderManager().initLoader(LOADER_ID, null,this);
mList = (ListView) findViewById(R.id.listView);
allList = m.getAllItems();
customAdapter = new CustomAdapter(this, allList);
mList.setAdapter(customAdapter);
final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// cast the IBinder and get MyService instance
UpdateServices.LocalBinder binder = (UpdateServices.LocalBinder) service;
myService = binder.getService();
bound = true;
myService.setCallbacks(MainActivity.this); // register
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
bound = false;
}
};
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
add();
// startService(new Intent(getApplicationContext(), UpdateServices.class));
}
});
if(!isMyServiceRunning(UpdateServices.class)) {
startService(new Intent(getApplicationContext(), UpdateServices.class));
}
// Intent intent = new Intent(getApplicationContext(), UpdateServices.class);
//bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// stopService(new Intent(getApplicationContext(), UpdateServices.class));
if (bound) {
myService.setCallbacks(null); // unregister
unbindService(serviceConnection);
bound = false;
}
}
});
}
public void add() {
DemoItem d = new DemoItem();
d.set("Fifty5Bytes", "Company");
m.addItem(d);
sampleLoader.onContentChanged();
}
@Override
public Loader<List<DemoItem>> onCreateLoader(int id, Bundle args) {
Log.i(TAG, "onCreateLoader");
sampleLoader = new SampleLoader(this);
return sampleLoader;
}
@Override
public void onLoadFinished(Loader<List<DemoItem>> loader, List<DemoItem> cursor) {
Log.i(TAG, "onLoadFinished " + cursor.size());
allList.clear();
allList.addAll(m.getAllItems());
customAdapter.notifyDataSetChanged();
mList.setSelection(allList.size() - 1);
}
@Override
public void onLoaderReset(Loader<List<DemoItem>> loader) {
// sampleLoader = null;
Log.i(TAG, "onLoaderReset");
}
/* @Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("ObjectA", sampleLoader);
}*/
@Override
public void doSomething() {
Log.i("do something","do something called");
sampleLoader.onContentChanged();
}
@Override
protected void onStop(){
try {
super.onStop();
}catch (Exception e){}
Log.i(TAG, "on stop called");
}
/** Lifecycle method: The final call received before the activity is destroyed. */
@Override
protected void onDestroy(){
try{
super.onDestroy();}
catch (Exception e){}
Log.i(TAG,"on destroy called");
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
Loader Class
public class SampleLoader extends AsyncTaskLoader<List<DemoItem>> implements Serializable {
public static final String TAG = "SampleLoader";
/** We hold a reference to the Loader’s data here.*/
private List<DemoItem> mData;
Context ctx;
public SampleLoader(Context ctx) {
super(ctx);
this.ctx = ctx;
ctx.registerReceiver(mObserver, new IntentFilter("my-event"));
}
@Override
public List<DemoItem> loadInBackground() {
// This method is called on a background thread and should generate a
// new set of data to be delivered back to the client.
MySQLiteHelper mySQLiteHelper = new MySQLiteHelper(ctx);
List<DemoItem> allItems = mySQLiteHelper.getAllItems();
Log.i(TAG,"Size : " + allItems.size());
return allItems;
}
@Override
public void deliverResult(List<DemoItem> data) {
if (isReset()) {
// The Loader has been reset;
releaseResources(data);
return;
}
// Hold a reference to the old data so it doesn't get garbage collected.
// We must protect it until the new data has been delivered.
List<DemoItem> oldData = mData;
mData = data;
if (isStarted()) {
// If the Loader is in a started state, deliver the results to the
// client. The superclass method does this for us.
super.deliverResult(data);
}
// Invalidate the old data as we don't need it any more.
if (oldData != null && oldData != data) {
releaseResources(oldData);
}
}
@Override
protected void onStartLoading() {
if (mData != null) {
// Deliver any previously loaded data immediately.
deliverResult(mData);
}
if (takeContentChanged() || mData == null) {
// When the observer detects a change, it should call onContentChanged()
// on the Loader, which will cause the next call to takeContentChanged()
// to return true. If this is ever the case (or if the current data is
// null), we force a new load.
forceLoad();
Intent intent = new Intent("my-event");
intent.putExtra("message", "message");
getContext().sendBroadcast(intent);
}
}
@Override
protected void onStopLoading() {
// The Loader is in a stopped state, so we should attempt to cancel the
// current load (if there is one).
cancelLoad();
// Note that we leave the observer as is. Loaders in a stopped state
// should still monitor the data source for changes so that the Loader
// will know to force a new load if it is ever started again.
}
@Override
protected void onReset() {
// Ensure the loader has been stopped.
onStopLoading();
Log.i("Onreset","Loader reset method called");
// At this point we can release the resources associated with 'mData'.
if (mData != null) {
releaseResources(mData);
mData = null;
}
// The Loader is being reset, so we should stop monitoring for changes.
if (mObserver != null) {
try {
getContext().unregisterReceiver(mObserver);
} catch (Exception e) {
e.printStackTrace();
}
mObserver = null;
}
}
@Override
public void onCanceled(List<DemoItem> data) {
// Attempt to cancel the current asynchronous load.
super.onCanceled(data);
// The load has been canceled, so we should release the resources
// associated with 'data'.
releaseResources(data);
}
private void releaseResources(List<DemoItem> data) {
// For a simple List, there is nothing to do. For something like a Cursor, we
// would close it in this method. All resources associated with the Loader
// should be released here.
}
private BroadcastReceiver mObserver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
//String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: ");
}
};
}
错误:
Activity com.aclass.asynctaskloader_01.MainActivity has leaked IntentReceiver com.aclass.asynctaskloader_01.SampleLoader$1@75cf002 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.aclass.asynctaskloader_01.MainActivity has leaked IntentReceiver com.aclass.asynctaskloader_01.SampleLoader$1@75cf002 that was originally registered here. Are you missing a call to unregisterReceiver()?
at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:918)
at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:719)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1172)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1152)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1146)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:554)
at com.aclass.asynctaskloader_01.SampleLoader.<init>(SampleLoader.java:29)
at com.aclass.asynctaskloader_01.MainActivity.onCreateLoader(MainActivity.java:125)
at android.app.LoaderManagerImpl.createLoader(LoaderManager.java:546)
at android.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:555)
at android.app.LoaderManagerImpl.initLoader(LoaderManager.java:609)
at com.aclass.asynctaskloader_01.MainActivity.onCreate(MainActivity.java:59)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
错误2
IllegalArgumentException: Receiver not registered:
com.aclass.asynctaskloader_01.SampleLoader$1@4c0db59
09-07 12:39:07.496 22126-22126/com.aclass.asynctaskloader_01 W/System.err:
at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:780)
09-07 12:39:07.496 22126-22126/com.aclass.asynctaskloader_01 W/System.err:
at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1195)
09-07 12:39:07.496 22126-22126/com.aclass.asynctaskloader_01 W/System.err:
at
android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:576)
09-07 12:39:07.496 22126-22126/com.aclass.asynctaskloader_01 W/System.err:
at com.aclass.asynctaskloader_01.SampleLoader.onReset(SampleLoader.java:116)