安卓动画如何减少卡顿和不流畅

26

我一直遇到动画问题,特别是当两个动画同时发生或在活动加载时。我明白这可能是资源问题,主线程中有很多事情导致动画卡顿。

我找到了一些有趣的建议:
1. 线程(ThreadPoolExecutor)
这里:如何使Android动画更流畅
2. setDrawingCacheEnabled(true)
这里:Android的setDrawingCacheEnabled()如何工作?
3. ViewGroup: animationCache = true
这里:http://www.curious-creature.org/2010/12/02/android-graphics-animations-and-tips-tricks/

但是我没有找到任何实现这些东西的示例。有什么想法吗?


AsyncTasks也是一种实现后台线程的简单方法。如果您在主线程中进行了大量计算,那么肯定需要实现线程或异步任务,因为主线程专门用于UI,而不是重活儿。 - Teovald
是的,我知道。我更想寻找使用线程/异步任务进行动画的示例。 - Rawr
2个回答

9

通过遵循以下减少动画卡顿的规则,我成功地降低了它们的频率:

  1. 不要在onCreateonStart 或者 onResume中启动动画。
  2. 在用户事件(比如onClick)中启动动画,直到动画完成前禁用触摸事件。
  3. 不要同时启动超过2个动画。

我们如何“在动画完成之前停止用户交互?” - Nam Vu
当您启动动画时,请设置一个变量,例如animStart = 1,并在处理按钮按下等操作时检查该变量。例如,如果您正在移动一个图层,则不希望用户在图层重新定位时按下按钮。因此,请设置变量,并在动画完成时取消设置它。 - Rawr
如何实现最佳方式?如果在加载活动时需要进行动画效果怎么办? - Si8
我不确定你所说的“最佳方法是什么”,实际上这取决于你想怎么做。至于第二部分,我认为在加载活动时不应该进行动画。相反,在活动加载完成后触发动画,并将布局最初设置为一些图片或图标,让用户知道“有东西正在进行中”。例如:最初,活动加载带有旋转器(一个繁忙的图标),一旦活动加载,触发一个函数来动画化任何您想要的内容并覆盖/删除“繁忙图标”。 - Rawr
@Rawr 我怎么知道一个活动完成加载了?有没有监听器? - Hai Hack
@HaiHack 这个问题/答案是一段时间之前的,所以我只能依靠记忆回答。我相信我通过加载静态占位符并在后台触发某些线程来处理 onResume 动画获得了最佳性能。 - Rawr

1
如果您正在使用动画,则应按照Android docs进行操作;实际上,在某些情况下,您可能需要暂时延迟片段转换。例如,在我的情况下,我需要推迟我的动画,直到我的viewmodel返回一些数据:
在进入的片段onViewCreated()方法中使用postponeEnterTransition()
public class A extends Fragment {

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        ...
        postponeEnterTransition();
    }
}

一旦数据准备好开始转换,调用startPostponedEnterTransition()

public class A extends Fragment {

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        postponeEnterTransition();

        final ViewGroup parentView = (ViewGroup) view.getParent();
        // Wait for the data to load
        viewModel.getData()
            .observe(getViewLifecycleOwner(), new Observer<List<String>>() {
                @Override
                public void onChanged(List<String> list) {
                    // Set the data on the RecyclerView adapter
                    adapter.setData(list);
                    // Start the transition once all views have been
                    // measured and laid out
                    parentView.getViewTreeObserver()
                        .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                            parentView.getViewTreeObserver()
                                .removeOnPreDrawListener(this);
                            startPostponedEnterTransition();
                            return true;
                        });
                }
        });
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接