首页 > 解决方案 > MainLooper 未执行 Android Runnable

问题描述

应用简要说明:

执行步骤为:

  1. 用户按下 Cordova UI 上的按钮
  2. Cordova 通过 cordova.exec(..) 执行本机插件方法
  3. 本机插件通过 cordova.startActivityForResult(..) 启动 CameraActivity 以获得结果
  4. CameraActivity 显示 AnaliseFragment
  5. AnaliseFragment 使用两个表面启动相机捕获会话:第一个显示在 TextureView 上,第二个由 ImageAnaliser 分析

问题:

UI 很少且随机地停止对用户和未在 UI 线程上执行的可运行对象做出反应。与此同时,后台线程继续正常工作:在 TextureView 上可以看到相机输出,并且 ImageAnaliser 继续从相机接收图像。

有没有人有任何建议如何找到/调试这种行为的原因?或者有什么想法会导致这种情况?

我已经尝试过:

下面是 AnaliseFragment 的简化代码:

public class AnaliseFragment extends Fragment {

private HandlerThread mBackgroundThread;
private Handler mBackgroundHandler;
private ImageAnalyser mImageAnalyser;

// listener is attached to camera capture session and receives every frame
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
    = new ImageReader.OnImageAvailableListener() {

    @Override
    public void onImageAvailable(ImageReader reader) {
        Image nextImage = reader.acquireLatestImage();
        mBackgroundHandler.post(() -> 
            try {
                mImageAnalyser.AnalizeNextImage(mImage);
            }
            finally {
                mImage.close();
            }
        );
    }
};

@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
    mImageAnalyser = new ImageAnalyser();
    mImageAnalyser.onResultAvailable(boolResult -> {
        // Runnable posted, but never executed
        new Handler(Looper.getMainLooper()).post(() -> reportToActivityAndUpdateUI(boolResult));
    });
}

@Override
public void onResume() {
    super.onResume();
    startBackgroundThread();
}

@Override
public void onPause() {
    stopBackgroundThread();
    super.onPause();
}

private void startBackgroundThread() {
    if (mBackgroundThread == null) {
        mBackgroundThread = new HandlerThread("MyBackground");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
    }
}

private void stopBackgroundThread() {
    mBackgroundThread.quitSafely();
    try {
        mBackgroundThread.join();
        mBackgroundThread = null;
        mBackgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

ImageAnalyser 的简化代码:

public class ImageAnalyser  {

public interface ResultAvailableListener {
    void onResult(bool boolResult);
}
private ResultAvailableListener mResultAvailableListener;   
public void onResultAvailable(ResultAvailableListener listener) { mResultAvailableListener = listener; }

public void AnalizeNextImage(Image image) {
    // Do heavy analysis and put result into theResult
    mResultAvailableListener.onResult(theResult);
}
}

标签: androidcordovacordova-pluginsandroid-looperandroid-threading

解决方案


UI线程中有一些长时间运行的操作。尝试分析您的应用程序以找出阻塞主线程的原因。


推荐阅读