Android-анимация работает, только если я перенесу ее из потока пользовательского интерфейса в поток пользовательского интерфейса - PullRequest
0 голосов
/ 09 января 2019

Я выполняю сетевой вызов, в котором я

.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

и затем я передаю результат в io.reactivex.function.Consumer, который пытается анимировать представление.

Эти анимации работали, когда я загружал данные локально и синхронно, но не работали, когда я вводил этот серверный вызов.

Теперь, когда я анимирую представления, он вообще не меняет никаких свойств, а просто мгновенно вызывает слушателя завершения анимации.

Я проверил, что я нахожусь в главном потоке с Looper.getMainLooper().isCurrentThread()

Тем не менее, единственный способ заставить анимацию работать снова - это обернуть ее в AndroidSchedulers.mainThread().scheduleDirect(() -> {})

Что, как показано в этом фрагменте кода, на самом деле ничего не должно изменить

 final Thread before = Thread.currentThread();
 AndroidSchedulers.mainThread().scheduleDirect(() -> {
     boolean nothingChanged = before == Thread.currentThread();
     //nothingChanged is true
 });

Почему я должен перенести анимацию обратно в поток, в котором она уже включена, чтобы заставить ее работать?

Редактировать: RxJava не участвует, что-то еще более странное. Я вырезал RxJava, и проблема воспроизводится, даже если я поместил код анимации в onNavigationItemSelected (), который вызывается android, когда пользователь что-то щелкает, поэтому он определенно находится в нужном потоке.

Моя анимация выглядит следующим образом.

alertBanner.clearAnimation();
alertBanner.animate()
        .alpha(0)
        .translationY(alertBanner.getHeight())
        .setDuration(500)
        .setListener(new AnimatorListenerBuilder().setOnAnimationEnd(animator -> {
            alertBanner.setVisibility(GONE);
        }))
        .start();

AnimatorListenerBuilder - это просто служебный класс, который упаковывает AnimatorListener и позволяет вам определять только те обратные вызовы, которые вы хотите. Он работает для всех остальных анимаций в моем приложении и не менялся месяцами.

1 Ответ

0 голосов
/ 10 января 2019

Я понял это. Это было состояние гонки.

Когда пользователь нажал кнопку, произошли две вещи: Был создан новый фрагмент и запущена анимация. Однако у фрагмента был обратный вызов onAttach(), который, помимо прочего, вызывал бы .clearAnimation() для представления, которое я пытался оживить.

Переместив анимацию обратно в основной поток, я убедился, что это произошло после обратного вызова фрагмента.

Я решил это, избавившись от обратного вызова из фрагмента и поместив эту логику в то же место, что и логика, запускающая анимацию, что позволяет мне контролировать порядок выполнения.

...