共同優勢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。