У меня есть требование создать растровое изображение из EditText, а затем выполнить некоторые манипуляции с ним.
Моя главная задача - не называть метод View.buildDrawingCache()
в потоке пользовательского интерфейса и, возможно, блокировать его, особенно когда речь идет о больших экранах (например, Nexus 10), поскольку EditText
будет занимать около 80% доступного размера экрана.
Я выполняю Runnable
внутри ThreadPoolExecutor
, они будут раздувать фиктивные представления рабочего потока и установить для них все необходимые атрибуты, а затем просто вызовите buildDrawingCache()
и getDrawingCache()
для создания растрового изображения.
Это отлично работает на некоторых устройствах, но в последнее время я столкнулся с несколькими устройствами, которые сбой со следующим сообщением:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Я понимаю, почему это происходит, поскольку некоторые телефоны должны иметь модифицированную реализацию для EditText
, которая создает Handler
и, следовательно, требуется сначала вызвать Looper.prepare()
.
Из того, что я читал в Интернете, нет проблемы с вызовом Looper.prepare() внутри рабочего потока, хотя некоторые заявили, что он очень не рекомендуется, но я не мог найти причину этого.
Кроме того, в большинстве сообщений, связанных с этой проблемой, говорится, что вы не должны раздувать представления в фоновом потоке, возможно, из-за следующих из официальной документации Android (процессы и потоки):
"Do not access the Android UI toolkit from outside the UI thread"
-
Каков рекомендуемый подход к решению этой проблемы?
-
Есть ли вред в вызове build/get drawingcache из основного потока? (С точки зрения производительности)
-
Будет ли вызов Looper.prepare() внутри рабочего потока решить эту проблему?
ИЗМЕНИТЬ
Чтобы подробно остановиться на моем конкретном требовании, у меня есть пользовательский интерфейс, состоящий из ImageView и пользовательского EditText поверх него, EditText может изменить его шрифт и цвет в соответствии с выбором пользователя, его можно увеличить/используя жестов "щепотка для увеличения", а также можно перетаскивать, чтобы пользователь мог переместить его поверх изображения.
В конечном итоге то, что я делаю, создает фиктивный вид внутри моего рабочего потока, используя те же самые значения (ширина, высота, положение), которые он имеет в настоящее время в пользовательском интерфейсе, а затем сгенерирует его рисование, исходное растровое изображение изображения снова декодируется из локального файл.
Как только два растровых изображения готовы, я объединю их в одно растровое изображение для будущего использования.
Итак, если это просто, есть ли что-то неправильное в выполнении следующего кода (из фона):
Вызов Looper.prepare()
Создайте новое представление с контекстом приложения, вызовите measure()
и layout()
вручную, а затем создайте + getcachecache из него, то есть:
Looper.prepare();
EditText view = new EditText(appContext);
view.setText("some text");
view.setLayoutParams(layoutParams);
view.measure(
View.MeasureSpec.makeMeasureSpec(targetWidth, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(targetHeight, View.MeasureSpec.EXACTLY));
view.layout(0, 0, targetWidth, targetHeight);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
Как это относится к ограничению без доступа к инструментарию Android UI из-за пределов пользовательского интерфейса, что может пойти не так?