3

我想按照这里的建议使用 AsyncTask 打开相机 http://developer.android.com/reference/android/hardware/Camera.html#open%28int%29

注意:在某些设备上,此方法可能需要很长时间才能完成。最好从工作线程(可能使用 AsyncTask)调用此方法,以避免阻塞主应用程序 UI 线程。

所以像:

onResume(){
    new AsyncTask(){
        doItInBackground(){
            camera_ref = Camera.open();
        }
    }.execute();
}

然后在 Pause() 我必须释放相机:

onPause(){ if(camera_ref!=null) camera_ref.release(); }

问题:我可以做些什么来确保在 release() 之后永远不会调用 open()?将 open() 放在带有布尔变量的同步块中不应该是一个解决方案,因为这仍然会阻塞 UI 线程。

一般来说,这个问题适用于我在回调方法中调用 camera_ref.something() 的所有情况......因为我必须确保这个调用只发生在 open() 和 release() 之间,而回调方法可以从每时每刻都有 UI 线程。

可能我错过了一些东西。我想看看应该怎么做。

编辑:截至目前,我认为最好的解决方案可能是使用 IntentService,如下所述:http: //developer.android.com/guide/components/services.html。尤其是:

IntentService 执行以下操作:

- Creates a default worker thread.
- Creates a work queue that passes one intent at a time.

这就是我一直在寻找的。使用 AsyncTask.executeOnExector(SINGLE_EXECUTOR) 是不可行的,因为 AsyncTasks 可能在开始之前就被杀死。我将进一步研究 ThreadPoolExecutor,看看它是否可能是一个替代方案。

4

1 回答 1

1

问题:我可以做些什么来确保在 release() 之后永远不会调用 open()?将 open() 放在带有布尔变量的同步块中不应该是一个解决方案,因为这仍然会阻塞 UI 线程。

onResume() 异步调用 open(),onPause() 调用 release(),所以你关心的是理论上如果 Activity 快速打开和关闭,它可能会调用 release() 然后 open()。所以使用 [isFinishing]1:

onResume(){
    release = false;
    new AsyncTask(){
        doItInBackground(){
            if (!isFinishing())
                camera_ref = Camera.open();
        }
    }.execute();
}

onPause(){ if(camera_ref!=null) camera_ref.release(); }

编辑:我的第一个答案是错误的:[

于 2013-07-12T18:43:27.113 回答