我有一个在后台运行的异步任务,它不断通过网络更新我的本地sqLite数据库。一切正常,除了我暂停我的应用程序后的一些随机时间。以下是我收到错误的代码的一部分:
public class AsyncHardwareDBUpdate extends AsyncTask {
ImageCellAdapter mImageCellAdapter;
GridView dynGrid;
Context mContext;
Boolean mFinished = false;
HardwareSyncReceiver myHardwareReceiver;
private Handler handler;
public AsyncHardwareDBUpdate(Context mContext) {
this.mContext = mContext;
}
@Override
protected Object doInBackground(Object... params) {
if (mContext != null){
错误转到以下行:
Intent intentHardwareSync = new Intent(mContext,SyncHardwareStateService.class);
我不明白,如果我已经检查过mContext!= null,那么这里可以为null。 其余的代码:
mContext.startService(intentHardwareSync);
myHardwareReceiver = new HardwareSyncReceiver();
//register BroadcastReceiver
IntentFilter intentHardwareSyncFilter = new IntentFilter(SyncHardwareStateService.ACTION_SyncHardwareStateService);
intentHardwareSyncFilter.addCategory(Intent.CATEGORY_DEFAULT);
//Handler for the separate Thread
HandlerThread handlerThread = new HandlerThread("MyNewThread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
// Create a handler for the service
handler = new Handler(looper);
// Register the broadcast receiver to run on the separate Thread
mContext.registerReceiver (myHardwareReceiver, intentHardwareSyncFilter, null, handler);
}
return null;
}
05-11 18:07:37.830: E/AndroidRuntime(15063): FATAL EXCEPTION: AsyncTask #1
05-11 18:07:37.830: E/AndroidRuntime(15063): java.lang.RuntimeException: An error occured while executing doInBackground()
05-11 18:07:37.830: E/AndroidRuntime(15063): at android.os.AsyncTask$3.done(AsyncTask.java:299)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-11 18:07:37.830: E/AndroidRuntime(15063): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.lang.Thread.run(Thread.java:856)
05-11 18:07:37.830: E/AndroidRuntime(15063): Caused by: java.lang.NullPointerException
05-11 18:07:37.830: E/AndroidRuntime(15063): at android.content.ContextWrapper.getPackageName(ContextWrapper.java:127)
05-11 18:07:37.830: E/AndroidRuntime(15063): at android.content.ComponentName.<init>(ComponentName.java:75)
05-11 18:07:37.830: E/AndroidRuntime(15063): at android.content.Intent.<init>(Intent.java:3350)
05-11 18:07:37.830: E/AndroidRuntime(15063): at com.smarthomev5.AsyncUpdateThread.AsyncHardwareDBUpdate.doInBackground(AsyncHardwareDBUpdate.java:38)
05-11 18:07:37.830: E/AndroidRuntime(15063): at android.os.AsyncTask$2.call(AsyncTask.java:287)
05-11 18:07:37.830: E/AndroidRuntime(15063): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-11 18:07:37.830: E/AndroidRuntime(15063): ... 5 more
答案 0 :(得分:3)
听起来像是内存泄漏。传递WeakReferences
或AsyncTasks
或其他此类对象时,始终在Context
中使用Activity
。尝试这样的事情:
public class ExampleAsyncTask extends AsyncTask<Void, Void, Boolean> {
private final WeakReference<Context> contextReference;
public ExampleAsyncTask(Context context) {
this.contextReference = new WeakReference<Context>(context);
}
@Override
protected Boolean doInBackground(Void... params) {
Context context = this.contextReference.get();
if(context != null) {
// Do your work
}
return false;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
Context context = this.contextReference.get();
if(context != null) {
// Do your work
}
}
}
WeakReference
做的是允许它引用的对象被垃圾收集。如果您直接保留引用,则无法对对象进行垃圾回收,这可能会导致Threads
和AsyncTasks
中的内存泄漏。例如,当您直接按住Context
引用并重新创建Activity
对象的Context
时,就会发生这种情况,例如当您旋转设备或Activity
时已经有一段时间了。
在上面的示例中,您将Context
对象保存在WeakReference
中,每次要使用Context
时,首先必须从WeakReference
获取该对象。从WeakReference
获得它之后,您只需检查它是否为空。如果它不是null,那么使用Context
是安全的。如果它是空的Context
或相应的Activity
已经被垃圾收集并且不再可用。