首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在运行doInBackground安卓系统后,AsyncTask无法完成

在运行doInBackground安卓系统后,AsyncTask无法完成
EN

Stack Overflow用户
提问于 2016-10-10 23:14:37
回答 4查看 982关注 0票数 0

我在我的TakePic类上运行一个AsyncTask。在doInBackground函数中,我使用了Camera.takePicture函数。现在一切正常;我正在拍摄照片并将文件保存到/sdcard/%d.jpg该位置。

代码语言:javascript
运行
复制
public class TakePic extends AsyncTask<CameraPreview, String, Integer> {

  @Override
  protected Integer doInBackground(final CameraPreview... params) {
          params[0].camera.takePicture(null,null,new Camera.PictureCallback() {
              @Override
              public void onPictureTaken(byte[] data, Camera camera) {
                  FileOutputStream outStream = null;
                  try {
                      outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
                      outStream.write(data);
                      outStream.close();
                      Log.e("picture_saved", "Picture has been saved succesfully: " + data.length);
                      camera.release();
                  } catch (FileNotFoundException e) {
                      e.printStackTrace();
                      Log.e("file_not_found: ","couldn't save the file "+e.getMessage());
                  } catch (IOException e) {
                      e.printStackTrace();
                      Log.e("IOexception: ","couldn't save the file "+e.getMessage());
                  }
              }
          });
      Log.e("doinback_compt:" ,"done");
      return 0;
  }

   @Override
   protected void onPostExecute(Integer integer) {
   }
}

但是在我的主类上执行这个AsyncTask之后,它并没有结束。我需要执行另一个函数,并且必须等到这个AsyncTask完成。因此,在执行AsyncTask之后,我使用while循环来检查任务的状态,但状态永远不会改变。

代码语言:javascript
运行
复制
    TakePic backCam=new TakePic();
    backCam.execute(cameraPreview_front);
    while (backCam.getStatus()!= AsyncTask.Status.FINISHED){
        *waiting for async task to finish*
    }

它停留在while循环中,我的logcat显示doInBackground运行正常,文件正保存到该位置。

代码语言:javascript
运行
复制
10-10 18:06:14.497 15975-15975/com.urun.camera_test E/clicked_capture:: ok
10-10 18:06:14.633 15975-16452/com.urun.camera_test E/doinback_compt:: done

那么我需要做什么呢?提前谢谢。

EN

回答 4

Stack Overflow用户

发布于 2016-10-10 23:59:53

这是以一种奇怪的方式处理的。首先,CameraPreview.camera.takePicture()将在后台运行,这就是为什么要在构造函数中将Camera.PictureCallback传递给它。您只是在那里堆叠线程。在主线程中尝试此操作

代码语言:javascript
运行
复制
[yourCameraPreview].camera.takePicture(null,null,new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        camera.release();
        // Read below
    }
}

现在我们可以等待图片回调。一旦我们得到数据,我们就可以调用AsyncTask将其存储在文件中,并应用我们自己的回调来等待它的响应。我们可以利用一个静态的内部类来实现这一切。

代码语言:javascript
运行
复制
private static class ImageSaver extends AsyncTask<Byte, Void, Exception>{

    public interface ImageSavedListener{
        void onImageSaved(Exception e);
    }

    private ImageSavedListener mCallback;

    public ImageSaver(ImageSavedListener callback){
        mCallback = callback;
    }

    @Override
    protected void doInBackground(Byte... data){
        if(data == null || data.length == 0)
            return new Exception("Data returned from camera is invalid");

        try {
            FileOutputStream outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
            outStream.write(data);
            outStream.close();
            Log.d("picture_saved", "Picture has been saved succesfully: " + data.length);
        } catch (FileNotFoundException e) {
            Log.e("file_not_found: ","couldn't save the file "+e.getMessage());
            return e;
        } catch (IOException e) {
            Log.e("IOexception: ","couldn't save the file "+e.getMessage());
            return e;
        }

        return null;
    }

    @Override
    protected void onPostExecute(Exception e){
        if(mCallback != null)
            mCallback.onImageSaved(e);
    }
}

然后这样叫它(在上面提到的Read below部分)

代码语言:javascript
运行
复制
new ImageSaver(new ImageSavedListener(){
    @Override
    public void onImageSaved(Exception e){
        if(e == null){
            // do what you want
        }
        else
            e.printStackTrace();
    }
}).execute(data);

这将在后台拍摄图片,等待响应,将响应保存到后台的文件中,等待响应,然后根据保存后返回的异常执行所需的操作。

票数 1
EN

Stack Overflow用户

发布于 2016-10-10 23:27:27

如果您需要在AsyncTask执行后执行一些代码,我可以建议一个解决方案。将*waiting for async task to finish*代码包装在Runnable中,并将其作为参数发送到异步任务(但这不是最好的解决方案,只是快速解决方案)

代码语言:javascript
运行
复制
    new AsyncTask<Object, Void, Runnable>() {
        @Override
        protected Runnable doInBackground(Object... runnables) {
            CameraPreview cp = (CameraPreview) runnables[0];
            Runnable callback = (Runnable) runnables[1];

            /**your main logic*/

            return callback;
        }

        @Override
        protected void onPostExecute(Runnable aVoid) {
            super.onPostExecute(aVoid);
            if (aVoid != null)
                aVoid.run();
        }
    }.execute( cameraPreview , new Runnable() {
        @Override
        public void run() {
            /**code to run();**/
        }
    });

当前代码可能存在的问题是:

您没有执行super.onPostExecute(integer);

尝试将代码更改为

代码语言:javascript
运行
复制
@Override
protected void onPostExecute(Integer integer) {
 super.onPostExecute(integer);
}
票数 0
EN

Stack Overflow用户

发布于 2016-10-10 23:48:13

正如前面指出的,阻塞你的主线程等待做某些事件是没有意义的。然而,如果你仍然想从你的AsyncTask中得到一些东西,我建议你使用FutureTask

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39961471

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档