美文网首页
面试准备

面试准备

作者: 老师好我是小明同学 | 来源:发表于2019-02-19 23:51 被阅读0次

    1.EventBus 源码分析

    (1) register 和 unregister
    private synchronized void register(Object subscriber, boolean sticky, int priority)
    
    image

    register 函数中会先根据订阅者类名去subscriberMethodFinder中查找当前订阅者所有事件响应函数,然后循环每一个事件响应函数,依次执行下面的 subscribe 函数:

    (2) subscribe

    subscribe 函数分三步
    第一步:通过subscriptionsByEventType得到该事件类型所有订阅者信息队列,根据优先级将当前订阅者信息插入到订阅者队列subscriptionsByEventType中;
    第二步:在typesBySubscriber中得到当前订阅者订阅的所有事件队列,将此事件保存到队列typesBySubscriber中,用于后续取消订阅;
    第三步:检查这个事件是否是 Sticky 事件,如果是则从stickyEvents事件保存队列中取出该事件类型最后一个事件发送给当前订阅者。

    (3) post、cancel 、removeStickyEvent

    post 函数用于发布事件,cancel 函数用于取消某订阅者订阅的所有事件类型、removeStickyEvent 函数用于删除 sticky 事件。
    post 函数流程图如下:

    image
    post 函数会首先得到当前线程的 post 信息PostingThreadState,其中包含事件队列,将当前事件添加到其事件队列中,然后循环调用 postSingleEvent 函数发布队列中的每个事件。

    postSingleEvent 函数会先去eventTypesCache得到该事件对应类型的的父类及接口类型,没有缓存则查找并插入缓存。循环得到的每个类型和接口,调用 postSingleEventForEventType 函数发布每个事件到每个订阅者。

    postSingleEventForEventType 函数在subscriptionsByEventType查找该事件订阅者订阅者队列,调用 postToSubscription 函数向每个订阅者发布事件。postToSubscription 函数中会判断订阅者的 ThreadMode,从而决定在什么 Mode 下执行事件响应函数。

    (4) 主要成员变量含义

    1.defaultInstance默认的 EventBus 实例,根据EventBus.getDefault()函数得到。
    2.DEFAULT_BUILDER默认的 EventBus Builder。
    3.eventTypesCache事件对应类型及其父类和实现的接口的缓存,以 eventType 为 key,元素为 Object 的 ArrayList 为 Value,Object 对象为 eventType 的父类或接口。
    4.subscriptionsByEventType事件订阅者的保存队列,以 eventType 为 key,元素为Subscription的 ArrayList 为 Value,其中Subscription为订阅者信息,由 subscriber, subscriberMethod, priority 构成。
    5.typesBySubscriber订阅者订阅的事件的保存队列,以 subscriber 为 key,元素为 eventType 的 ArrayList 为 Value。
    6.stickyEventsSticky 事件保存队列,以 eventType 为 key,event 为元素,由此可以看出对于同一个 eventType 最多只会有一个 event 存在。
    7.currentPostingThreadState当前线程的 post 信息,包括事件队列、是否正在分发中、是否在主线程、订阅者信息、事件实例、是否取消。currentPostingThreadState是一个ThreadLocal,他的特点是获取当前线程一份独有的变量数据,不受其他线程影响。
    8.mainThreadPosterbackgroundPosterasyncPoster事件主线程处理者、事件 Background 处理者、事件异步处理者。
    9.subscriberMethodFinder订阅者响应函数信息存储和查找类。
    10.executorService异步和 BackGround 处理方式的线程池。

    via:http://a.codekk.com/detail/Android/Trinea/EventBus%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90

    2.View 事件传递

    传递 dispatchTouchEvent() --> 拦截 onInterceptTouchEvent() --> 消费
    onTouchEvent()
    onInterceptTouchEvent、onTouchEvent 在 dispatchTouchEvent 里
    (1) 事件从 Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的 View(ViewGroup)开始一直往下(子 View)传递。子 View 可以通过 onTouchEvent()对事件进行处理。
    (2) 事件由父 View(ViewGroup)传递给子 View,ViewGroup 可以通过 onInterceptTouchEvent()对事件做拦截,停止其往下传递。
    (3) 如果事件从上往下传递过程中一直没有被停止,且最底层子 View 没有消费事件,事件会反向往上传递,这时父 View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到 Activity 的 onTouchEvent()函数。
    (4) 如果 View 没有对 ACTION_DOWN 进行消费,之后的其他事件不会传递过来。
    (5) OnTouchListener 优先于 onTouchEvent()对事件进行消费。

    3.Glide 源码

    Glide.with()

    创建一个 具有生命感知的Fragment 绑定到 Activity/Fragment 上面

    public static RequestManager with(FragmentActivity activity) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(activity);
        }
    
        public RequestManager get(FragmentActivity activity) {
            if (Util.isOnBackgroundThread()) {
                return get(activity.getApplicationContext());
            } else {
                assertNotDestroyed(activity);
                FragmentManager fm = activity.getSupportFragmentManager();
                return supportFragmentGet(activity, fm);
            }
        }
    
        RequestManager supportFragmentGet(Context context, FragmentManager fm) {
            SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
            RequestManager requestManager = current.getRequestManager();
            if (requestManager == null) {
                requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
                current.setRequestManager(requestManager);
            }
            return requestManager;
        }
    
        SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
            SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
            if (current == null) {
                current = pendingSupportRequestManagerFragments.get(fm);
                if (current == null) {
                    // 创建一个 Fragment 绑定到 Activity 上面
                    current = new SupportRequestManagerFragment();
                    pendingSupportRequestManagerFragments.put(fm, current);
                    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                    handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
                }
            }
            return current;
        }
    

    Glide的图片加载过程中会调用两个方法来获取内存缓存,loadFromCache()和loadFromActiveResources()。这两个方法中一个使用的就是LruCache算法,另一个使用的就是弱引用

    内存缓存(LruCache算法 + 弱引用) 先LruCache 后 弱引用 HashMap
    硬盘缓存的实现也是使用的LruCache算法
    LruCache主要算法原理就是把最近使用的对象用强引用存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。

    Glide.with(context).resumeRequests()和 Glide.with(context).pauseRequests()
            当列表在滑动的时候,调用pauseRequests()取消请求,滑动停止时,调用resumeRequests()恢复请求。
    
             圆形图片
             .apply(RequestOptions.bitmapTransform(new CircleCrop()))
             
             圆角图片
             .apply(RequestOptions.bitmapTransform(new RoundedCorners(20))) // 圆角半径
    

    4.设计模式

    1.单例模式

    /**
     * 单例模式
     */
    public class Singleton {
    
        private static volatile Singleton instance;
    
        private Singleton(){}
    
        /**
         * 双重验证DCL
         */
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized(Singleton.class) {
                    if (instance == null)
                        instance = new Singleton();
                }
            }
            return instance;
        }
    
        /**
         * 静态内部类单例模式
         */
        public static Singleton getInstance() {
            return SingletonHolder.singleton;
        }
    
        public static class SingletonHolder {
            private static final Singleton singleton = new Singleton();
        }
    
    }
    

    2.工厂方法模式
    Product、ProductA extends Product、BaseFactory1、FactoryA extends BaseFactory1

    BaseFactory1 factory = new FactoryA();
    Product product = factory.createProduct();

    /**
     * 工厂方法
     */
    public class FactoryMothod {
        public abstract class Product {
            public abstract void method();
        }
        
        public class ProductA extends Product {
    
            @Override
            public void method() {
            }
        }
        
        public abstract class BaseFactory1 {
            public abstract Product createProduct();
        }
        
        public class FactoryA extends BaseFactory1 {
    
            @Override
            public Product createProduct() {
                return new ProductA();
            }
        }
    
        public abstract class BaseFactory2 {
            public abstract <T extends Product> T createProduct(Class<T> clz);
        }
        
        public class FactoryB extends BaseFactory2 {
    
            @Override
            public <T extends Product> T createProduct(Class<T> clz) {
                Product p = null;
                try {
                    p = (Product) Class.forName(clz.getName()).newInstance();
                } catch (Exception e) {
                    e.printStackTrace();
                } 
                return (T) p;
            }
        }
        
        public void test() {
            BaseFactory1 factory = new FactoryA();
            Product product = factory.createProduct();
            
            BaseFactory2 factory2 = new FactoryB();
            Product product1 = factory2.createProduct(ProductA.class);
        }
        
    }
    

    3.Builder 设计模式

    public class Student2 {
    private final int id;
    private final String name;
    private int age;
    
    private Student2(){}   //定义私有构造器,只能在类内部使用(提供给静态内部类创建一个对象)
    
    private Student2(Student2 origin){  // 拷贝一个对象,即把静态内部类对象的属性给外部类,由静态内部类调用
        this.id = origin.id;  
        this.name = origin.name; 
        this.age = origin.age;
    }
    
    public int getId(){
        return this.id;
    }
    
    public String getName(){
        return this.name;
    }
    
    public int getAge(){
        return this.age;
    }
    
    public static class Builder{  //静态内部类,通过该类来创建一个外部类对象,使用链式调用
        private Student2 target;  //创建一个外部类对象
        
        /**
         * 构造一个内部类对象,通过该对象设置属性值
         * 如果存在必填参数,可以以带参构造函数的方式传过来
         * @param id  必填参数
         * @param name 必填参数
         */
        public Builder(int id , String name){ 
            target= new Student2();
            target.id = id;
            target.name = name;
        }
        
        /**
         * 调动builder对象的id方法设置id值
         * 返回builder对象,用来下一个方法设置属性值
         * 这就是链式调用
         * @param id
         * @return
         */
        
        
        public Builder age(int age){
            target.age = age;
            return this;
        }
        
        
        /**
         *
         * @return
         */
        public Student2 build(){
            Student2 st = new Student2(target); //调用外部类的带参构造函数初始化外部类的参数
            
            if(st.id < 100)   //builder模式是线性不安全的,所以我们必须要类创建完毕后才能对异常处理           
            try{
                throw new IllegalStateException("Age out of range"); // 非线程安全
            }
            catch( IllegalStateException e){
                st.id = 1000;
                e.printStackTrace();
            }
            return st; //返回一个外部类
        }
    }
    
    
    public static void main(String [] args){
        Student2 st = new Student2.Builder(1, "hubin").id(23).build();
        System.out.println(st.getId());
    }
    

    4.观察者模式

    /**
     * 观察者模式
     */
    public class ObserverModel {
        public class Coder implements Observer {
            public String name;
            public Coder(String name) {
                this.name = name;
            }
            @Override
            public void update(Observable o, Object arg) {
                Log.e("tag", "name:" + arg);
            }
        }
        
        public class DevNews extends Observable {
            public void postNews(String name) {
                setChanged();
                notifyObservers();
            }
        }
        
        public void test() {
            Coder coder1 = new Coder("1");
            Coder coder2 = new Coder("2");
            DevNews devNews = new DevNews();
            devNews.addObserver(coder1);
            devNews.addObserver(coder2);
        }
    }
    

    5.算法

    image

    1.冒泡排序


    image
    /**
         * 冒泡排序
         *  比较相邻的元素。如果第一个比第二个大,就交换它们两个;
         *  对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
         *  针对所有的元素重复以上的步骤,除了最后一个;
         *  重复步骤1~3,直到排序完成。
         *  时间: O(n2)
         */
        public static int[] bubbleSort(int[] array) {
            if (array.length == 0) return array;
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array.length - 1 - i; j++) {
                    if (array[j + 1] < array[j]) {
                        int temp = array[j + 1];
                        array[j + 1] = array[j];
                        array[j] = temp;
                    }
                }
            }
            return array;
        }
    

    2.选择排序


    image
      /**
         * 选择排序
         *  首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
         *  然后,再从剩余未排序元素中继续寻找最小(大)元素,
         *  然后放到已排序序列的末尾。
         *  以此类推,直到所有元素均排序完毕。
         *  时间: O(n2)
         */
        public static int[] selectionSort(int[] array) {
            if (array.length == 0) return array;
    
            for (int i = 0; i < array.length; i++) {
                int minIndex = i;
                // 从确定的最小的后一位开始到最后,每次循环结束将最小的放前面
                for (int j = i; j < array.length; j++) {
                    if (array[j] < array[minIndex]) {
                        // 将最小数的索引保存
                        minIndex = j;
                    }
                }
                int temp = array[minIndex];
                array[minIndex] = array[i];
                array[i] = temp;
            }
    
            return array;
        }
    

    3.快速排序


    image image.png
        /**
         * 快速排序
         *  快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
         *  从数列中挑出一个元素,称为 “基准”(pivot);
         *  重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
         *  在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
         *  递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
         */
        public static int[] quickSort(int[] array, int start, int end) {
            if (array.length < 1 || start < 0 || end > array.length || start > end) return null;
            int smallIndex = partition(array, start, end);
            if (smallIndex > start)
                quickSort(array, start, smallIndex - 1);
            if (smallIndex < end)
                quickSort(array, smallIndex + 1, end);
            return array;
        }
    
        /**
         * 快速排序算法
         */
        public static int partition(int[] array, int start, int end) {
            int pivot = (int) (start + Math.random() * (end - start + 1));
            int smallIndex = start - 1;
            swap(array, pivot, end);
            for (int i = start; i <= end; i++)
                if (array[i] <= array[end]) {
                    smallIndex++;
                    if (i > smallIndex)
                        swap(array, i, smallIndex);
                }
            return smallIndex;
        }
    
        /**
         * 交换数组内两个元素
         */
        public static void swap(int[] array, int i, int j) {
            int temp = array[i];
            array[i] = array[j];
            array[j] = temp;
    }                  
    ```

    相关文章

      网友评论

          本文标题:面试准备

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