共同优势html
不一样点java
图片框架的缓存android
glide源码
通常看源码先看他的使用方法,经过使用的方法看对应的代码。
Glide.with(MainActivity.this).load(url).into(headerImage);git
public Request getRequest() { //本质仍是getTag Object tag = getTag(); Request request = null; if (tag != null) { if (tag instanceof Request) { request = (Request) tag; } else { throw new IllegalArgumentException("You must not call setTag() on a view Glide is targeting"); } } return request; } @Override public void setRequest(Request request) { //本质是setTag setTag(request); }
对图片加载用到了LruCache(最少最近使用)算法
他会把内存控制在必定大小内,超过最大值时会自动回收,这个最大值能够本身定,一个过小的缓存空间,有可能形成图片频繁地被释放和从新加载,这并无好处。而一个太大的缓存空间,则有可能仍是会引发 java.lang.OutOfMemory 的异常。通常使用最大可用内存的1/8做为缓存的大小。LruCache的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap (频繁增删、不须要排序)中,而且把最近最少使用的对象在缓存值达到预设定值以前从内存中移除。 github
public class BitmapCache implements ImageCache { private LruCache<String, Bitmap> mCache; public BitmapCache() { int maxSize = 10 * 1024 * 1024; mCache = new LruCache<String, Bitmap>(maxSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight(); } }; } @Override public Bitmap getBitmap(String url) { return mCache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { mCache.put(url, bitmap); } }
经常使用网络库使用方法算法
public interface netApi { @GET("repos/{owner}/{repo}/contributors") Call<ResponseBody> contributorsBySimpleGetCall(@Path("owner") String owner, @Path("repo") String repo); } public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); volleyStringRequest(); volleyJsonRequest(); retrofitHttpRequest(); try { okhttpAsyGet(); OkHttpSyncGet(); } catch (Exception e) { e.printStackTrace(); } } //volley第一步 RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this); private void volleyStringRequest() { //volley第二步 StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.d("TAG", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); //volley第三步 mQueue.add(stringRequest); } private void volleyJsonRequest() { JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://www.sina.com/sports/101010100.html", null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.d("TAG", response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); mQueue.add(jsonObjectRequest); } //okhttp第一步 private final OkHttpClient client = new OkHttpClient(); public void okhttpAsyGet() throws Exception { //okhttp第二步 Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); //okhttp第三步 okhttp3.Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } System.out.println(response.body().string()); } public void OkHttpSyncGet() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, okhttp3.Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0, size = responseHeaders.size(); i < size; i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } System.out.println(response.body().string());//只能获取一次,能够用string保存 } }); } public void retrofitHttpRequest() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); netApi repo = retrofit.create(netApi.class); retrofit2.Call<ResponseBody> call = repo.contributorsBySimpleGetCall("userName", "path"); call.enqueue(new retrofit2.Callback<ResponseBody>() { @Override public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) { //response } @Override public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) { } }); } } String post(String url, String json) throws IOException { RequestBody formBody = new FormEncodingBuilder() .add("platform", "android") .add("name", "bug") .add("subject", "XXXXXXXXXXXXXXX") .build(); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } }
volley原理
主线程中调用RequestQueue的add()方法来添加一条网络请求,这条请求会先被加入到缓存队列当中,若是发现能够找到相应的缓存结果就直接读取缓存并解析,而后回调给主线程。若是在缓存中没有找到结果,则将这条请求加入到网络请求队列中,而后处理发送HTTP请求,解析响应结果,写入缓存,并回调主线程。json
为何说Volley适合数据量小,通讯频繁的网络操做
volley中为了提升请求处理的速度,采用了ByteArrayPool进行内存中的数据存储的,若是下载大量的数据,这个存储空间就会溢出,因此不适合大量的数据,可是因为他的这个存储空间是内存中分配的,当存储的时候优是从ByteArrayPool中取出一块已经分配的内存区域, 没必要每次存数据都要进行内存分配,而是先查找缓冲池中有无适合的内存区域,若是有,直接拿来用,从而减小内存分配的次数 ,因此他比较适合据量小,通讯量大网络数据交互状况。api
Retrofit原理缓存
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
本身写网络请求框架服务器
@Override public Response execute() throws IOException { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); timeout.enter(); eventListener.callStart(this); try { client.dispatcher().executed(this); Response result = getResponseWithInterceptorChain(); if (result == null) throw new IOException("Canceled"); return result; } catch (IOException e) { e = timeoutExit(e); eventListener.callFailed(this, e); throw e; } finally { client.dispatcher().finished(this); } }
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); interceptors.addAll(client.interceptors()); interceptors.add(retryAndFollowUpInterceptor); interceptors.add(new BridgeInterceptor(client.cookieJar())); interceptors.add(new CacheInterceptor(client.internalCache())); interceptors.add(new ConnectInterceptor(client)); if (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(forWebSocket)); Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest, this, eventListener, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis()); return chain.proceed(originalRequest); }
//线程池,核心线程数为0,最大线程数为最大整数,线程空闲存活时间60s,//SynchronousQueue 直接提交策略 private static final Executor executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE , 60L , TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp ConnectionPool", true)); //空闲链接的最大链接数 private final int maxIdleConnections; //保持链接的周期 private final long keepAliveDurationNs; //双端队列,存放具体的链接 private final Deque<RealConnection> connections = new ArrayDeque<>(); //用于记录链接失败的route final RouteDatabase routeDatabase = new RouteDatabase(); //构造函数//从这里能够知道,空闲链接的最大链接数为5,保持链接的周期是5分钟 public ConnectionPool() { this(5, 5, TimeUnit.MINUTES); } public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) { this.maxIdleConnections = maxIdleConnections; this.keepAliveDurationNs = timeUnit.toNanos(keepAliveDuration); // Put a floor on the keep alive duration, otherwise cleanup will spin loop. if (keepAliveDuration <= 0) { throw new IllegalArgumentException("keepAliveDuration <= 0: " + keepAliveDuration); } }
自定义一个拦截器
class LoggingInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); logger.info(String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime(); logger.info(String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); return response; } }
LeakCanary原理解析
Evenbus是作什么的?和RXjava有什么区别?
黏性事件
简单讲,就是在发送事件以后再订阅该事件也能收到该事件,跟黏性广播相似,可是它只能收到最新的一次消息,好比说在未订阅以前已经发送了多条黏性消息了,而后再订阅只能收到最近的一条消息。
EventBus源码 register(this)就是去当前类,遍历全部的方法,找到onEvent开头的而后进行存储(把匹配的方法最终保存在subscriptionsByEventType(Map,key:eventType ; value:CopyOnWriteArrayList<Subscription> ),eventType是咱们方法参数的Class,Subscription中则保存着subscriber, subscriberMethod(method, threadMode, eventType), priority;包含了执行改方法所需的一切),而后post的时候,根据post传入的参数,去找到匹配的方法,反射调用。数据传递是经过handler。