3

Я хочу использовать AsyncTask, чтобы открыть камеру, как предложено здесь http://developer.android.com/reference/android/hardware/Camera.html#open%28int%29:камеры Открытие с помощью AsyncTask

Внимание: На некоторых устройствах, этот метод может занять много времени, чтобы закончить. Лучше всего вызвать этот метод из рабочего потока (возможно, используя AsyncTask), чтобы избежать блокировки потока пользовательского интерфейса основного приложения.

Так что-то вроде:

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

затем в на Pause() я должен освободить камеру:

OnPause() { если (camera_ref! = NULL) camera_ref. выпуск(); }

Вопрос: Что я могу сделать, чтобы быть уверенным, что open() никогда не будет вызван после release()? Включение open() внутри синхронизированного блока с булевой переменной не должно быть решением, поскольку это все равно блокирует поток пользовательского интерфейса.

В целом, эта проблема относится ко всем ситуациям, когда я вызываю функцию camera_ref.something() внутри метода обратного вызова ... поскольку я должен убедиться, что этот вызов происходит только между open() и release(), в то время как метод обратного вызова может быть вызванным из потока пользовательского интерфейса в каждый момент.

Возможно, у меня что-то не хватает. Я хотел бы видеть, как это должно быть сделано.

EDIT: На данный момент я считаю, что лучшим решением может быть использование 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, чтобы узнать, может ли это быть возможной альтернативой.

+0

Я посмотрел на код для встроенного приложения камеры и ее все очень нечеткие !!! При первом создании Activity камера открывается в потоке, но затем в конце onCreate соединение создается на этом потоке, таким образом, возможно, все еще будет бить UIThread. Кроме того, в остальной части кода метод open() вызывается непосредственно из потока пользовательского интерфейса. Я еще раз посмотрю ... может быть, я неправильно понял ...но на данный момент похоже на это. –

ответ

1

Вопрос: Что я могу сделать, чтобы быть уверенным, что open() никогда не будет вызван после release()? Помещение open() внутри синхронизированного блока с логической переменной не должно быть решением, поскольку это все равно блокирует поток пользовательского интерфейса.

onResume() вызывает открытое() асинхронно, и OnPause() вызывает высвобождение(), так что ваша проблема в том, что в теории, если активность открывается и закрывается быстро, он может позвонить релиз() и затем откройте() , Так что используйте [isFinishing] 1:

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

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

Edit: мой первый ответ был неправ: [

+0

В моем сценарии, где функция camera.open() вызывается после camera.release(), эталонная камера_ref всегда имеет значение null во время onPause()! Так что это ничего не изменит. Возможно, у вас есть неверная информация ... camera.open() is Camera.open(), которая является статическим методом ... Я ее отредактировал, извините. Это не решит проблему callbacs, потому что часть кода test + camera.operation() должна находиться внутри синхронизированного блока, что, возможно, блокирует поток пользовательского интерфейса. –

Смежные вопросы