1 introduction

Google I/O has released a series of utility tools to assist Android developers, called Jetpack, that enable developers to quickly and easily create high-quality applications with superior performance by providing modern application architectures and robust backward compatibility. This series will cover five areas:

  • Arch: Thread management, flexible increase of deleted map links
  • Lifecycle links
  • Data driven: LiveData, ViewModel links
  • Database Room link
  • Background job scheduling

This chapter introduces some of the frameworks that depend on the above content, mainly the following image, including two aspects: thread pooling and quick removal of map data;

2 the thread pool

2.1 TaskExecutor classes

Abstract class that defines call methods wrapped in thread pools

  • ExecuteOnDiskIO (@nonNULL Runnable Runnable) : Abstract method, executed in AN IO thread
  • PostToMainThread (@nonNULL Runnable Runnable) : Abstract method committed to the main thread for execution
  • ExecuteOnMainThread (@nonNULL Runnable Runnable) : Execute the mainThread immediately, otherwise commit it to the main thread
  • Boolean isMainThread() : Abstract method, whether main thread

2.2 DefaultTaskExecutor class

Implement the TaskExecutor class;

2.2.1 executeOnDiskIO method

Thread pool execution; Thread pool is a thread with two fixed core threads; And the thread name: arch_disk_io_ number

2.2.2 postToMainThread method

Using the Handler mechanism, the main thread Handler is used for processing. And the handler object used lazy loading, double judgment + lock to achieve the goal of single instance

2.2.3 isMainThread method

To determine whether a thread is the master thread, the main thread instance is fetched from the main thread looper instance in the Handler mechanism

2.3 ArchTaskExecutor class

Also implements the TaskExecutor class; It is also a proxy class that implements TaskExecutor; Its proxy implementation is an instance of DefaultTaskExecutor, or it can be set using the class method setDelegate. In addition, it can be called in two ways. Rich and convenient for users to call more flexible

  • Handled by a unique instance
  • Static method to obtain the corresponding thread pool instance for processing; It is also handled internally by calling a unique instance

2.4 summary

Overall, the library provides a default implementation for thread pool switching and thread pool calls; We should pay attention to:

  1. There is no thread pool exit or end method, and the default thread pool has only two fixed core threads; This indicates that asynchronous task execution is less frequent and time-consuming, that is, the task execution queue is too long
  2. Use ArchTaskExecutor as the entry point for unified control

3 Delete the map iteratively

Function interface specifies the input to output interface, also can be said to be A converter to B; The other two classes are iteratively delete security maps

3.1 SafeIterableMap

Implement the Iterable< map. Entry<K, V>> class; The whole thing is a set of bidirectional linked lists

    Entry<K, V> mStart;
    private Entry<K, V> mEnd;
    private WeakHashMap<SupportRemove<K, V>, Boolean> mIterators = new WeakHashMap<>();
    private int mSize = 0;
Copy the code
  • Entry: Data structure containing key and value data fields and pointer fields before and after. MStart the first data, mEnd the last data
  • SupportRemove interface: Quickly deletes current iteration data during iteration
  • MSize: indicates the data size
  • MIterators: A collection of iterator weak references that support quick deletion

It is clear that data is stored in the form of a bidirectional linked list. Its addition, deletion and iteration are accessed through the pointer field of the list, and are judged and processed by the equal method. But there is a special treatment, as shown in the red box below

When data is deleted, if the referenced iterator exists, synchronization is maintained, and elements in the iterator content are also deleted

There are three types of mIterators store iterators that implement the SupportRemove interface, and iterators are obtained using the following methods

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: Iterate back to front <>(mEnd, mStart); mIterators.put(iterator, false); return iterator; } public IteratorWithAdditions iteratorWithAdditions() { @SuppressWarnings("unchecked") IteratorWithAdditions iterator =  new IteratorWithAdditions(); mIterators.put(iterator, false); return iterator; }Copy the code
  • AscendingIterator: iterate from front to back
  • DescendingIterator: Iterates backwards
  • IteratorWithAdditions: Iterates over elements that have already been iterated

3.2 FastSafeIterableMap class

Inherit SafeIterableMap, and use HashMap class to store data in internal data. The data stored in HashMap is a value pair composed of key-entry <key,value>. Use SafeIterableMap to implement safe deletion of iterators

@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; }Copy the code

3.3 summary

The data structure only provides the method of add and delete, and there is no get method, and the iterator is treated with special treatment (safe delete), so it can be seen that this data structure uses the data store in listening mode. And the iterators we’ve seen before

  1. The current iteration remove method throws an exception directly
  2. The current iterator can operate on the corresponding set during iteration

In the iteration, the iterator can delete elements, but when the collection is added and deleted, an exception is thrown; Iterators introduced in this article are exceptions when iterators themselves delete elements, while collections can be added and deleted. So the question is, what’s the difference between these two, and what’s the advantage of each? The author think

  1. The iterators implemented by the previous collection were relatively simple and were more suitable for scenarios where the iteration required processing and deletion of the corresponding elements
  2. The two sets in this paper, which increase the synchronization logic of iterators, are relatively complex, but can be added and deleted, and use more flexible; Can solve the problem of operation nesting; For example, in listener mode, one of the listeners registers or deregistry the event during event distribution. See the LifecycleRegistry class, where there is an urgent need to resolve this scenario. For those of you who are not quite sure why, please check out my next article jetpack source code – Lifecycle

Technology changes quickly, but the basic technology, the theoretical knowledge is always the same; The author hopes to share the basic knowledge of common technical points in the rest of his life. If you think the article is well written, please pay attention and like it. If there are mistakes in the article, please give me more advice!