Подтвердить что ты не робот

Надуть представление в фоновом потоке

У меня очень простой вопрос:

Невозможно ли надуть представление (не добавлять его в макет) в фоновом потоке (например: в doInBackground AsyncTask)?

Я знаю, что это возможно, потому что я реализовал большинство Деяний в своем приложении таким образом и никогда не испытывал проблем, пока у меня не возникла эта проблема на Galaxy S: Android: android.view.InflateException: двоичная строка XML файла # 13: ошибка раздувания класса <unknown> в SAMSUNG Galaxy S

Мне сказали, что я не должен надувать Views в фоновом потоке, но каковы конкретные причины и почему мой aproach работает на большинстве устройств, но не в Galaxy S?

4b9b3361

Ответ 1

LayoutInflater не делает никаких предположений о том, в какой поток он работает. И об этом не упоминается в документации. Также его кодовые швы должны быть нитевидными.

С другой стороны, представления, созданные LayoutInflater, могут создавать экземпляры Handler в своих конструкторах. Ну, они, вероятно, не должны этого делать, но нет требования, чтобы они не создавали/не использовали Handler в своих конструкторах.

Я предполагаю, что Samsung Galaxy S имеет некоторые модификации в своем EditText, который каким-то образом запускает создание Handler (в соответствии с журналом сбоев из вашего другого экземпляра вопроса GestureDetector был создан экземпляр, который, в свою очередь, создал новый Handler). Хотя реализация по умолчанию не делает этого.


В целом, я бы сказал, что, поскольку для View нет явного требования не использовать Handler и Looper в своих конструкторах, вы не можете предположить, что раздувание представлений из потока, отличного от UI, безопасно.

Фактически вы можете создать HandlerThread и попробовать раздуть View внутри него. Но я бы сказал, что это очень рискованно, так как в примере Samsung Galaxy S представление предполагает, что этот поток будет жив в течение View lifetime и обработает все сообщения, используя его Looper. Это может привести к сбою позже.

Ответ 2

С новейшей поддержкой lib вы можете использовать android.support.v4.view.AsyncLayoutInflater для азартного раздувания просмотров. Будьте осторожны, хотя это может привести к раздуванию потока пользовательского интерфейса, если конкретные требования не выполняются:

Для того, чтобы макет был завышен асинхронно, он должен иметь родителя, чей generateLayoutParams (AttributeSet) является потокобезопасным, а все Представления, созданные как часть инфляции, не должны создавать обработчиков или иначе вызывать myLooper(). Если макет, который пытается быть завышенным, не может быть сконструирован асинхронно по любой причине, AsyncLayoutInflater автоматически вернется к раздуванию в потоке пользовательского интерфейса.

Ответ 3

Возможно ли раздуть представление (не добавлять его в макет) в фоновый поток (например: в doInBackground из AsyncTask)?

Возможно, да. Рекомендуемые? Нет. Как указано в документации:

Таким образом, для модели с одним потоком в Android существует всего два правила:

  • Не блокируйте поток пользовательского интерфейса
  • Не обращайтесь к инструментарию Android UI из-за пределов пользовательского интерфейса.

через: Процессы и потоки