簡體   English   中英

運行doInBackground Android后AsyncTask沒有完成

[英]AsyncTask doesn't finish after running doInBackground Android

我在TakePic類上運行AsyncTask。 doInBackground函數中,我正在使用Camera.takePicture函數。 現在一切都很好。 我正在拍照並將文件保存到/sdcard/%d.jpg該位置。

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循環來檢查任務的狀態,但是狀態永遠不會改變。

    TakePic backCam=new TakePic();
    backCam.execute(cameraPreview_front);
    while (backCam.getStatus()!= AsyncTask.Status.FINISHED){
        *waiting for async task to finish*
    }

它停留在while循環中,我的logcat顯示doInBackground運行正常,並且文件正在保存到該位置。

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

那我該怎么辦? 提前致謝。

這是用一種奇怪的方式來處理的。 第一個CameraPreview.camera.takePicture()將在后台運行,這就是為什么在構造函數Camera.PictureCallback其傳遞給Camera.PictureCallback的原因。 您只是在這里堆疊線程。 在主線程中嘗試

[yourCameraPreview].camera.takePicture(null,null,new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        camera.release();
        // Read below
    }
}

現在我們可以等待圖片回調。 取回數據后,我們可以調用AsyncTask將其存儲在文件中,並應用我們自己的回調以等待其響應。 我們可以利用靜態內部類來使所有這些工作。

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的部分” Read below

new ImageSaver(new ImageSavedListener(){
    @Override
    public void onImageSaved(Exception e){
        if(e == null){
            // do what you want
        }
        else
            e.printStackTrace();
    }
}).execute(data);

這將在后台拍照,等待響應,將響應保存到后台的文件中,等待響應,然后根據保存后返回的異常執行所需的操作。

如果您需要在執行AsyncTask之后執行一些代碼,我可以建議一種解決方案。 Runnable包裝*waiting for async task to finish*代碼,並將其作為參數發送給Async任務(但這不是最好的解決方案,只是快速的解決方案)

    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);

嘗試將代碼更改為

@Override
protected void onPostExecute(Integer integer) {
 super.onPostExecute(integer);
}

如前所述,阻塞您的主線程等待做某些事件是沒有意義的。 但是,如果您仍然想從AsyncTask中得到一些東西,我建議您使用FutureTask

正如我在您的代碼中看到的那樣,AsyncTask正在正確完成。 問題是您正在AsyncTask中拍照。 因此,當Camera.PictureCallback等待圖片時,在調用“ takePicture”方法后任務立即結束。

我應該做的是這樣的(這只是一種方法):

  public class TakePic {

    public interface MyTakePicListener{
        void onPictureTaken();
        void onPictureError();
    }

    private MyTakePicListener myListener; 


    public void takePicture(CameraPreview cameraPreview) {
        cameraPreview.camera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(final byte[] data, final Camera camera) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        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();

                            HERE you should call a listener to continue with your success code
                            myListener.onPictureTaken();
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                            Log.e("file_not_found: ", "couldn't save the file " + e.getMessage());

                            HERE you should call a listener to continue with your error code
                            myListener.onPictureError();
                        } catch (IOException e) {
                            e.printStackTrace();
                            Log.e("IOexception: ", "couldn't save the file " + e.getMessage());

                            HERE you should call a listener to continue with your error code
                            myListener.onPictureError();
                        }

                        Log.e("doinback_compt:", "done");



                    }
                }).start();
            }

        });
    }

}

請讓我知道這是否可以幫助您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM