Jetpack源码-arch篇

1,324 阅读5分钟

1 前言

谷歌I/O 发布了一系列辅助android开发者的实用工具,合称Jetpack,其通过提供现代化应用架构以及提供强健的向后兼容能力等方式,让开发者能够快速、轻松地创造拥有卓越性能的高质量应用。本系列文章会介绍一下5个方面:

  • arch:线程管理、灵活增加删除的map 链接
  • 生命周期lifecycle 链接
  • 数据驱动:livedata、viewmodel 链接
  • 数据库Room 链接
  • 后台作业调度 链接

本章内容主要介绍上面内容中一些依赖的框架,主要是下面图片的内容,包括两个方面线程池和快速删除map数据;

jichu.png

2 线程池

2.1 TaskExecutor类

抽象类,定义了线程池包装的调用方法

  • executeOnDiskIO(@NonNull Runnable runnable): 抽象方法,io线程中执行
  • postToMainThread(@NonNull Runnable runnable):抽象方法,提交到主线程执行
  • executeOnMainThread(@NonNull Runnable runnable):当前为主线程则立即执行,否则提交到主线程执行
  • boolean isMainThread():抽象方法,是否主线程

2.2 DefaultTaskExecutor类

实现了TaskExecutor类;

2.2.1 executeOnDiskIO方法

采用线程池执行;线程池为两个固定核心线程的线程;并且线程命名:arch_disk_io_数字

2.2.2 postToMainThread方法

借用Handler机制,使用主线程Handler来进行处理;并且对handler对象采用了懒加载,双重判断+锁来达到实例单一的目标

2.2.3 isMainThread方法

判断线程是否为主线程,主线程实例由Handler机制中主线程looper实例中获取

2.3 ArchTaskExecutor类

也是实现了TaskExecutor类;同时也是实现了TaskExecutor的代理类;其代理实现是DefaultTaskExecutor实例,也可使用类方法setDelegate来设置 另外其调用有两种方式。丰富并且方便用户更灵活的调用

  • 通过唯一实例来处理
  • 静态方法获取相应线程池实例进行处理;其内部也是调用唯一实例来处理

2.4 小结

整体来说,此库提供了线程池的切换以及线程池调用的默认实现;我们在使用时应该注意:

  1. 未提供线程池退出或者结束方法,默认线程池也只有两个固定核心线程;这表明异步执行任务频率比较低、耗时比较少,也就是注意任务执行排队过久问题
  2. 使用ArchTaskExecutor作为调用入口,整体统一控制

3 迭代删除map

Function接口主要,规定了输入到输出的一种接口,也可以说是A转换成B的一种转换器;另外两个类是迭代删除安全map

3.1 SafeIterableMap

实现Iterable<Map.Entry<K, V>>类;整体来说是一个由双向链表组成的集合

    Entry<K, V> mStart;
    private Entry<K, V> mEnd;
    private WeakHashMap<SupportRemove<K, V>, Boolean> mIterators = new WeakHashMap<>();
    private int mSize = 0;
  • Entry:含有key、value数据域以及前后的指针域的数据结构;mStart第一个数据,mEnd最后一个数据
  • SupportRemove接口:迭代中快速删除当前迭代数据
  • mSize:数据大小
  • mIterators:支持快速删除的迭代器弱引用集合

很明了,采用双向链表的形式来存储数据,其添加、删除、迭代就是通过链表的指针域访问,并通过equal方法来判断处理的;但是其中有个特殊处理地方,如下图红框内容

diedaishanchu.png

删除数据的时候,若引用的迭代器存在,则保持同步,迭代器内容中同样删除元素

mIterators存储迭代器类型有三种且均实现了SupportRemove接口,且迭代器获取如下方法

    public Iterator<Map.Entry<K, V>> iterator() {
        ListIterator<K, V> iterator = new AscendingIterator<>(mStart, mEnd);
        mIterators.put(iterator, false);
        return iterator;
    }

    public Iterator<Map.Entry<K, V>> descendingIterator() {
        DescendingIterator<K, V> iterator = new DescendingIterator: 从后往前迭代
        <>(mEnd, mStart);
        mIterators.put(iterator, false);
        return iterator;
    }

    public IteratorWithAdditions iteratorWithAdditions() {
        @SuppressWarnings("unchecked")
        IteratorWithAdditions iterator = new IteratorWithAdditions();
        mIterators.put(iterator, false);
        return iterator;
    }
  • AscendingIterator: 从前往后迭代
  • DescendingIterator: 从后往前迭代
  • IteratorWithAdditions:从已迭代元素继续往后迭代

3.2 FastSafeIterableMap类

继承SafeIterableMap,并且内部数据使用HashMap类存储数据,HashMap存储的数据,则是key-Entry<key,value>组成的值对;利用SafeIterableMap来实现迭代器的安全删除

    @Override
    public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> current = get(key);
        if (current != null) {
            return current.mValue;
        }
        mHashMap.put(key, put(key, v));                                // 1
        return null;
    }

    @Override
    public V remove(@NonNull K key) {
        V removed = super.remove(key);                                // 2
        mHashMap.remove(key);
        return removed;
    }

3.3 小结

数据结构只向外提供增加、删除方法,并没有get方法,而且对迭代器进行了特殊处理(安全删除),由此可见此种数据结构使用监听模式的数据存储;和我们之前接触的迭代器的区别

  1. 当前的迭代remove方法,直接抛出异常
  2. 当前迭代器在迭代过程中相应集合可以进行操作

之前的集合都涉及的:其迭代器在迭代中,迭代器删除元素可以,但是集合进行增加删除时抛出异常;文章中介绍的迭代器迭代器自身删除元素时异常,而集合可以进行增加删除;那么问题来了,这两种有什么区别,各有什么优势呢?作者觉得

  1. 之前集合实现的迭代器相对简单,而且更适合迭代中需要处理以及删除相应元素的场景
  2. 文章中的两种集合,增加了迭代器的同步逻辑,相对比较复杂,但可以增加删除,使用更加灵活;能解决这种操作嵌套的问题;比如监听者模式中:在事件分发时,其中某个监听者又注册或者解注了事件,详见LifecycleRegistry类中,其中急需要解决这种场景;不太清楚为何的同学,请查查看我的下一篇文章jetpack源码-lifecycle篇

技术变化都很快,但基础技术、理论知识永远都是那些;作者希望在余后的生活中,对常用技术点进行基础知识分享;如果你觉得文章写的不错,请给与关注和点赞;如果文章存在错误,也请多多指教!