Я столкнулся с очень странной особенностью.
Когда я пытаюсь запустить анимацию в основном потоке, она не запускается. Когда я запускаю указанную анимацию, используя
getView().post(new Runnable() {
@Override
public void run() {
getView().startAnimation(a);
}
});
Это действительно начинается.
Я распечатал CurrentThread
перед запуском анимации, и оба печатаются main
.
Очевидно, мне здесь чего-то не хватает, так как оба должны запускать анимацию в основном потоке ... Я предполагаю, что, когда сообщение добавляет задачу в очередь, она запускается в более "правильное время", но я хотел бы знать что здесь происходит более подробно.
РЕДАКТИРОВАТЬ: Позвольте мне прояснить ситуацию - мой вопрос в том, почему запуск анимации в сообщении вызывает ее запуск, а при запуске анимации в основном потоке - нет.
AnimationDrawable
! ОбычныйAnimation
экземпляр начал успешно анимироваться при каждой настройке. ВAnimationDrawable
случае; когда вы пытаетесь запустить егоonCreate
, он не запускается, потому что в этот момент не привязан к просмотру. Так что это не проблема многопоточностиAnimationDrawable
. Может быть, то же самое относитсяAnimation
? developer.android.com/guide/topics/graphics/…Ответы:
post : post вызывает добавление Runnable в очередь сообщений,
Runnable: представляет команду, которую можно выполнить. Часто используется для запуска кода в другом потоке.
run () : запускает выполнение активной части кода класса. Этот метод вызывается при запуске потока, созданного с помощью класса, реализующего Runnable.
код :
getView().startAnimation(a);
в вашем коде,
post заставляет Runnable ( код будет запущен в другом потоке) добавить очередь сообщений.
Итак, startAnimation будет запущен в новом потоке, когда он будет получен из messageQueue.
[ИЗМЕНИТЬ 1]
Почему мы используем новый поток вместо потока пользовательского интерфейса (основного потока)?
UI поток:
При запуске приложения Ui Thread создается автоматически
он отвечает за отправку событий в соответствующие виджеты, включая события рисования.
Это также поток, с которым вы взаимодействуете с виджетами Android.
Что произойдет, если пользователь нажмет кнопку, которая будет работать долго?
Пользовательский интерфейс зависает. Программа может даже вылететь.
Это нарушает правило Android, которое никогда не обновляет пользовательский интерфейс непосредственно из рабочего потока.
Android предлагает несколько способов доступа к потоку пользовательского интерфейса из других потоков.
Как показано ниже,
View.post (запускаемый)
Обработчик
Для получения дополнительной информации
http://android-developers.blogspot.com/2009/05/pxygen-threading.html
http://www.aviyehuda.com/blog/2010/12/20/android-multithreading-in-a-ui-environment/
источник
Это делается в onCreate или onCreateView? Если это так, приложение может не находиться в состоянии, в котором View прикреплен к окну. Многие алгоритмы, основанные на показателях представления, могут не работать, поскольку такие вещи, как измерения и положение представления, возможно, не были рассчитаны. Анимации Android обычно требуют, чтобы они выполняли математику пользовательского интерфейса.
View.post фактически ставит анимацию в очередь в цикле сообщений View, поэтому, как только представление прикрепляется к окну, оно выполняет анимацию вместо того, чтобы запускать ее вручную.
На самом деле вы запускаете что-то в потоке пользовательского интерфейса, но в другое время
источник
Поищите здесь хороший ответ. view.post () во многом аналогичен handler.post (). Он попадает в очередь основного потока и запускается после завершения других ожидающих задач. Если вы вызовете activity.runOnUiThread (), он будет вызываться немедленно в потоке пользовательского интерфейса.
источник
Я думаю, проблема может заключаться в методе жизненного цикла, в котором вы вызываете метод post (). Вы делаете это в onCreate ()? если да, посмотрите, что я нашел в документации по активности onResume ():
https://developer.android.com/reference/android/app/Activity.html#onResume ()
Итак, как сказал Джо Планте, возможно, представление не готово для запуска анимации в тот момент, когда вы вызываете post (), поэтому попробуйте переместить его в onResume ().
PD: На самом деле, если вы переместите код в onResume (), я думаю, вы можете удалить вызов post (), поскольку вы уже находитесь в потоке пользовательского интерфейса, и представление должно быть готово для запуска анимации.
источник
onResume
может вызываться несколько раз (экраны переходят в спящий режим, активность помещается в стопку и т. д.) после того, как изначально "представление готово". ЕслиonResume
вызывается из , тогда может потребоваться флаг для отслеживания погоды, когда анимация уже была запущена, чтобы избежать (повторного) запуска несколько раз.