美文网首页工作生活
Android-Lottie与线程池结合产生的问题

Android-Lottie与线程池结合产生的问题

作者: RookieRun | 来源:发表于2019-07-04 17:58 被阅读0次

1.背景:项目中底部的tab动画使用的Lottie实现的,最近发现如下问题:

问题:1.动画未显示
    问题:2.动画显示之前,切换tab 在动画文件加载之后会导致多个选中的情况
    问题:3.断网的情况下,动画可以正常显示

2.问题分析:

项目中,首页新增一个LottieAnimationView,网速较慢的情况下,也不能显示
项目中,二级页面新增一个LottieAnimationView,网速较慢的情况下,也不能显示

当前的首页启动时,异步任务过多,UI线程被worker线程抢占,那为什么网速好的情况下,不会出现这种情况呢?
由此可见,LottieAnimationView的渲染,也是异步的,或者说,至少json文件的读取是异步的,在网速不好的情况下,多个异步任务无法及时返回,而线程池中的异步任务排队无法被及时执行,导致LottieAnimationView对应的json文件无法及时被读取,从而导致界面空白
那解决措施,就是,1.优化项目中异步任务的执行2.提高LottieAnimationView的线程优先级

3.代码分析:

项目中,引用的lottie是2.3.0,而该版本的LottieComposition类中的JsonCompositionLoader(用来执行json的加载和解析的)在执行异步任务的时候,使用的是AsyncTask默认的线程池(AsyncTask.THREAD_POOL_EXECUTOT)

 /**
     * Loads a composition from a raw json object. This is useful for animations loaded from the
     * network.
     */
    public static Cancellable fromJson(Resources res, JSONObject json,
        OnCompositionLoadedListener loadedListener) {
      JsonCompositionLoader loader = new JsonCompositionLoader(res, loadedListener);
      loader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, json);
      return loader;
    }
项目中的网络请求等耗时操作,也是使用的AsyncTask默认的线程池,
该线程池的CorePoolSize(核心线程数)是4个,最大线程数量17个,
工作队列是128个(数量因手机不同而有差异,公式不变)。
而打印的日志也发现,的确在初始化异步请求的时候,该方法的调用次数达到了40+,
而17个最大线程数量,显然会导致,部分异步任务会被放置到队列中。
image.png
AsyncTask
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

以上就导致了当并行的任务过多,网速较慢的时候,队列中的异步任务排队过久的情况,进而导致了上述问题

解决:

方案1,修改项目中异步任务使用的线程池,可行
方案2,修改LottieAnimationView,可行,但是有局限性, 虽然可以解决这个lottie的问题,
但是,从整个项目层面上来考虑,不够完美,而且,需要修改lottie的源码

相关文章

  • Android-Lottie与线程池结合产生的问题

    1.背景:项目中底部的tab动画使用的Lottie实现的,最近发现如下问题: 2.问题分析: 当前的首页启动时,异...

  • ThreadPoolExecutor实战(一:线程池参数)

    线程池是什么? 线程池是多线程开发中关键技术之一,线程池能够提高系统性能,是为了优化直接创建线程产生的问题而存在的...

  • 针对保证线程池的创建 利用枚举保证单例的线程安全

    对于线程池,单例,枚举的结合 项目使用同一个线程池,需要保证线程池的唯一,不能到处创建线程池,这个时候使用单例,但...

  • JDK(1.8)线程池源码探究:ThreadPoolExecut

    结合JDK(1.8)源码分析线程池(ThreadPoolExecutor)实现原理 我们平时所提的线程池,大多指的...

  • Callable与线程池结合使用

    等一万次加加执行完后,才会输出。主要原因是在integer = result.get();这个方法上。Future...

  • 多线程-线程池

    线程池 by shihang.mai Beofre:我们创建线程和运行是结合在一起的 After:我们利用线程池可...

  • 线程池

    线程池解决的核心问题:资源管理问题。 线程池运行机制最主要的三个点: 线程池如何维护自身状态; 线程池如何管理任务...

  • springBoot结合线程池解决多线程问题实录

    背景: 线上有一个接口,3台机器总共QPS在3000左右,单机QPS在1000左右,接口响应时间2ms。为了保证接...

  • 八、线程池剖析

    一、前置问题 线程的状态转换 为什么要使用线程池 线程池的继承体系 线程池使用的场景 线程数的设置规则 线程池的状...

  • 线程池

    线程池基础概念 线程池是什么 线程池是一种基于池化思想的线程管理工具 线程池解决了哪些问题 降低资源消耗(操作系统...

网友评论

    本文标题:Android-Lottie与线程池结合产生的问题

    本文链接:https://www.haomeiwen.com/subject/cmarhctx.html