在我的应用程序中,我打电话给相机应用程序拍照。 在我的活动结果中,我启动了一个asynctask来处理照片。 (旋转并上传照片)。
我还想从图库中删除照片。 为此,我在asynctask中执行以下代码。
// Delete image from gallery
String[] imageColumns = { MediaStore.Images.Media._ID };
String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
String imageWhere = MediaStore.Images.Media._ID + ">?";
String[] imageArguments = { Integer.toString(captureLastID) };
CursorLoader imageLoader = new CursorLoader(mActivity);
imageLoader.setUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imageLoader.setProjection(imageColumns);
imageLoader.setSelection(imageWhere);
imageLoader.setSelectionArgs(imageArguments);
imageLoader.setSortOrder(imageOrderBy);
Cursor imageCursor = imageLoader.loadInBackground();
if (imageCursor.getCount() > 0) {
while (imageCursor.moveToNext()) {
int id = imageCursor.getInt(imageCursor
.getColumnIndex(MediaStore.Images.Media._ID));
ContentResolver cr = mActivity.getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.Images.Media._ID + "=?",
new String[] { Long.toString(id) });
break;
}
}
imageCursor.close();
我收到错误
无法在未调用Looper.prepare
的线程内创建处理程序
导致此错误的原因是什么?如何解决? 它是否与我调用loadInBackground这一事实有关,而asynctask已经在后台运行了?
这是我的logcat:
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.support.v4.content.Loader$ForceLoadContentObserver.<init>(Loader.java:52)
at android.support.v4.content.CursorLoader.<init>(CursorLoader.java:96)
at tasks.ProcessPictureTask.doInBackground(ProcessPictureTask.java:78)
at tasks.ProcessPictureTask.doInBackground(ProcessPictureTask.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
... 4 more
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.support.v4.content.Loader$ForceLoadContentObserver.<init>(Loader.java:52)
at android.support.v4.content.CursorLoader.<init>(CursorLoader.java:96)
at tasks.ProcessPictureTask.doInBackground(ProcessPictureTask.java:78)
at tasks.ProcessPictureTask.doInBackground(ProcessPictureTask.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
答案 0 :(得分:11)
实际上,接受的答案是不正确的。您似乎对发生这种情况的原因感兴趣,它也可能有助于您的应用程序的响应性,所以我会给出另一个答案:
您没有改变用户界面,因此这不是导致此次崩溃的原因。原因是您的后台线程没有与之关联的Looper,因为错误说明了。 looper是偶尔检查消息的消息队列。例如,当您使用Handler时,它就是您使用的。
只需在崩溃应用程序的调用之前添加以下代码行即可添加looper:
Looper.prepare();
在后台线程上而不是在UI线程上执行大量查询有一个很大的优势,因为在加载游标时,UI不会响应。如果响应对您很重要,则应在后台线程上调用db。
现在,在这种情况下,CursorLoader确实没有理由需要looper。就我所知,至少只是笨拙的实现,抛出异常。实际上,如果你使用LoaderManager,使用CursorLoader会更容易。
如果您不想使用加载器和后台线程,那么更简单的方法是使用registerListener(int, OnLoadCompleteListener)
设置一个侦听器并使用startLoading()
开始加载。这会自动为您处理所有线程,并可能为您节省一些代码。
答案 1 :(得分:2)
您正尝试在后台线程中执行UI操作,您应该在UI线程中运行它。
答案 2 :(得分:2)
您正在攻击MVC模式,因为您正在尝试从AsynTask中的onBackground方法更新UI组件,因此您收到此错误。 将任何UI或初始化移动到Post或Pre execute方法。 看来:
CursorLoader imageLoader = new CursorLoader(mActivity);
必须放在protected void onPreExecute () method.