一、

2018-07-25  本文已影响9人  最美下雨天
1、Retrofit的实现与原理

Retrofit是基于OkHttp,可以通过注解来配置请求方法的类型、请求参数、可以使用多种converter对数据进行解析,比如最常见的json、xml,并且支持rxjava,我觉得Retrofit中最核心的设计模式应该是动态代理,在利用构建者模式build出Retrofit对象后,一般直接调用retrofit的create(Class service)方法,service是个接口类,包装了访问服务器的方法, create方法中直接对service做了动态代理, 以后我们在调用service中的方法时,都会被代理,代理类中最主要的执行了三行代码

ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

loadServiceMethod是将一个接口中的带注解的普通方法适配为一个http方法,这里会对method方法上的注解进行解析,包括baseurl、请求方法的类型(get、put)、请求参数等,然后利用serviceMethod构建了一个okHttpCall,这个类定义了一些同步、异步方法(就是真正要去请求网络的),然后第三部调用callAdapter的adapt方法,这个callAdapter方法是从adapterFactories集合中取的,就是在返回请求结果时做线程切换用的,如果在构建Retrofit时配置了rxjava,那么就是rxjava的,如果没有的话是从platform中取的,这个platform就是代表的Android,它也是利用了handler

new Handler(Looper.getMainLooper())

传递的是主线程的looper

@Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(final Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(call, new IOException("Canceled"));
              } else {
                callback.onResponse(call, response);
              }
            }
          });
        }

        @Override public void onFailure(final Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(call, t);
            }
          });
        }
      });
    }

这儿的callbackExecutor.execute其实就是执行的handler.post

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
2、HashMap、ConcurrentHashMap

HashMap的主干是一个存放Entry(键值对)的数组,数组的长度默认是16,HashMap中最常见的两个方法是get、put。在put一个Entry的时候,首先会根据key计算出一个哈希值,然后将这个Entry放到数组的对应位置上,如果这个位置上已经有值了,那么就会在该位置生成一个链表,新元素插入到该位置上,新元素的next指向旧元素,在get的时候,也是先计算出key的哈希值,然后去数组对应的位置上查找Entry,如果key不相等,顺着链表往后查找。
HashMap的默认长度是16,并且每次自动扩展或者手动初始化指定长度时也必须是2的幂,这样做的目的是为了实现一个尽量均匀分布的hash函数,HashMap的哈希算法采用了位运算符index = HashCode(Key) & (Length - 1),与2的幂次方减一进行&运算,Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。
jdk1.8后HashMap的数据结构变为了数组+链表+红黑树,链表长度大于8时转换为红黑树
参考文章:https://blog.csdn.net/login_sonata/article/details/76598675
高并发情况:
https://blog.csdn.net/qfzhangwei/article/details/69938937
多线程put的时候可能导致元素丢失 、put非null元素后get出来的却是null
1.8以下,假设一个HashMap已经到了Resize的临界点。此时有两个线程A和B,在同一时刻对HashMap进行Put操作,两个线程各自执行resize然后rehash可能导致环形链表的出现,再执行get操作的时候会出现死循环
1.8中没有这个问题了。

3、红黑树

参考文章https://www.cnblogs.com/CarpenterLee/p/5503882.html
TreeMap

4、类加载机制

类从被加载到虚拟机内存开始到卸载出内存为止,它的整个生命周期包括了7个阶段,加载、验证、准备、解析、初始化、使用、卸载

a.加载阶段:主要完成三件事

b.验证阶段:
这一阶段的主要目的是为了确保Class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

c.准备阶段:
准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间

d.解析阶段:
解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程

f.初始化阶段:
初始化阶段是类加载最后一个阶段,执行类构造器<client>方法

5、requestLayout,invalidate,postInvalidate区别与联系
上一篇 下一篇

猜你喜欢

热点阅读