如何在异步函数后触发活动更改

时间:2016-12-19 02:19:04

标签: java android

我正在开发一个OCR应用程序,在从相机获取实时更新并找到所需文本后,我开始了一个"报告活动"将OCR的结果报告给用户。它工作正常,但我想让应用程序在更改活动之前拍摄相机的图片。我包含了我当前的Java类,我在PictureCallback中启动了活动。问题是,有时应用程序会更改活动,而其他应用程序(和调试程序)只会冻结。非常感谢帮助理解为什么会发生这种情况以及如何解决它。

来自OpticalProcessor类(活动是初始化期间传递的当前活动)

@Override
public void receiveDetections(Detector.Detections<TextBlock> detections) {
    Intent intent = new Intent(activity.getBaseContext(), ReportActivity.class);
    int flag = 0;

    //Perform OCR Processing

    if (flag > 3) {
        Log.d("Test", "Testing 1234454");
        startAct(intent, activity);
    }
}

private void startAct (final Intent intent, final Activity act) {
    ((OcrCaptureActivity) activity).mCameraSource.takePicture(new com.embocorp.utils.receipt.ocrreader.ui.camera.CameraSource.ShutterCallback() {
        @Override
        public void onShutter() {
            Log.d("New", "New");
        }
    }, new com.embocorp.utils.receipt.ocrreader.ui.camera.CameraSource.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data) {
            Log.d("Move", "mobe");
            Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
            saveToInternalStorage(bmp, getCurrentTimeStamp(), act, intent);
            act.startActivity(intent);
        }
    });
}

private String saveToInternalStorage(Bitmap bitmapImage, String name) {
    ContextWrapper cw = new ContextWrapper(activity.getApplicationContext());
    File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
    File mypath=new File(directory, name + ".jpg");

    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(mypath);
        bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
           fos.close();
        } catch (IOException e) {
           e.printStackTrace();
        }
    }

    return directory.getAbsolutePath();
}

1 个答案:

答案 0 :(得分:1)

据我所知,我不知道为什么有什么东西在冻结。你很可能在某个地方锁定了UI线程。

就问题标题而言:如果您的回调设置正确,异步代码将得到最佳处理。

例如,我看到你有一对高度耦合的类,其中一个只有一堆回调处理相机。

我的建议是没有显式的Activity,你试图访问该类的任何字段。例如((OcrCaptureActivity) activity).mCameraSource.takePicture,而如果你真的需要那个类(或者更确切地说是mCameraSource),那么你应该给出它。另一方面,活动本身可以实现这些回调,这就是startActivity和所有这些事情的所在。

import com.embocorp.utils.receipt.ocrreader.ui.camera.CameraSource;

public class OpticalProcessor {
    // TODO: Implement other interfaces here for receiveDetections method?

    private final Context mContext;
    private CameraSource.ShutterCallback shutterCallback;   
    private CameraSource.PictureCallback pictureCallback;
    private OnDetectionsReceievedListener detectionListener;

    public interface OnDetectionsReceievedListener {
        void onDetectionsReceived(Detector.Detections<TextBlock> detections);
    }

    public OpticalProcessor(Context c) {
        this(c, null, null);
    }

    public OpticalProcessor(Context c, CameraSource.ShutterCallback shutterCallback, CameraSource.PictureCallback pictureCallback) {
        this.mContext = c;
        setShutterCallback(shutterCallback);
        setPictureCallback(pictureCallback);
    }

    public void takePicture(CameraSource camera) {
        if (this.shutterCallback != null && this.pictureCallback != null) {
            camera.takePicture(this.shutterCallback, this.pictureCallback);
        } else {
            Log.w("OpticalProcessor::takePicture", "Shutter or Picture callbacks have not been set!");
        }
    }    

    public void setShutterCallback(CameraSource.ShutterCallback shutterCallback) {
        this.stutterCallback = shutterCallback;
    }

    public void setPictureCallback(CameraSource.PictureCallback pictureCallback) {
        this.pictureCallback = pictureCallback;
    }

    public void setDetectionListener(CameraSource.PictureCallback pictureCallback) {
        this.detectionListener = detectionCallback;
    }

    @Override
    public void receiveDetections(Detector.Detections<TextBlock> detections) {
        // Maybe this is needed? 
        if (detectionListener != null) {
            detectionListener.onDetectionsReceived(detections);
        }

        // Perform OCR Processing
        int tag = 0;
        if (tag > 3) { // Why would this have worked? It's set at 0...
            Log.d("Test", "Testing 1234454");
        }
    }
}

正如我所说,Activity实现了回调并将它们传递到相应的位置。

我假设您正在尝试拍摄照片以响应某些点击事件。

import com.embocorp.utils.receipt.ocrreader.ui.camera.CameraSource;

public class OcrCaptureActivity extends Activity 
    implements CameraSource.ShutterCallback, CameraSource.PictureCallback, 
     OpticalProcessor.OnDetectionsReceievedListener {

    private CameraSource mCameraSource;

    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
        // setContentLayout...

        ...

        mCameraSource = ???

        // Pass the context and the listeners here
        final OpticalProcessor processor = new OpticalProcessor(this, this, this);
        processor.setDetectionListener(this); 

        someButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                processor.takePicture(mCameraSource);
            }
        });
    }

    // This method could really be anywhere as long as it has a Context
    public static String saveToInternalStorage(Context ctx, Bitmap bitmapImage, String name) {
        File directory = ctx.getDir("imageDir", Context.MODE_PRIVATE);
        File path=new File(directory, name + ".jpg");

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
               fos.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
        }

        return directory.getAbsolutePath();
    }

    @Override
    public void onShutter() {
        Log.d("New", "New");
    }

    @Override
    public void onPictureTaken(byte[] data) {
        Log.d("Move", "mobe");
        Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
        saveToInternalStorage(this, bmp, getCurrentTimeStamp());

        // Activity started here
        startActivity(new Intent(this, ReportActivity.class));
    }

    @Override
    public void onDetectionsReceived(Detector.Detections<TextBlock> detections) {
        // Perform OCR Processing??
    }
}