Volley框架之一 如何使用

一直想找個優秀的開源框架學習下,Volley非常合適,研究下來學到了不少知識

Volley簡介

Volley可是說是把AsyncHttpClient和Universal-Image-Loader的優點集於了一身,既可以像AsyncHttpClient一樣非常簡單地進行HTTP通信,也可以像Universal-Image-Loader一樣輕鬆加載網絡上的圖片。除了簡單易用之外,Volley在性能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網絡操作,而對於大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。

先解釋一下,對於大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕,爲什麼呢? 因爲我們知道對於大文件的下載,我們一般的處理方式是把網絡輸入流直接寫入文件,不寫入內存,這樣有效防止OOM,但是Volley,並沒有針對大文件下載做任何處理,還是通用的實現,先寫入內存,然後寫入硬盤緩存。

導入Volley庫

Google官方的Volley
android studio中添加volley
So Volley has been updated to Android studio build style which makes it harder create a jar. But the recommended way for eclipse was using it as a library project and this goes for android studio as well, but when workgin in android studio we call this a module. So here is a guide to how do it the way Google wants us to do it. Guide is based on this nice tutorial.

  1. First get latest volley with git (git clone https://android.googlesource.com/platform/frameworks/volley).
  2. In your current project (android studio) click [file] –[Import Module].
  3. Now select the directory where you downloaded Volley to.
  4. Now Android studio might guide you to do the rest but continue guide to verify that everything works correct
  5. Open settings.gradle (find in root) and add (or verify this is included):
    include ‘:app’, ‘:volley’
  6. Now go to your build.gradle in your project and add the dependency:
    compile project(“:volley”)

Thats all there is to it, much simpler and easier than compiling a jar and safer than relying on third parties jars or maven uploads.

另一個經常用的是 mcxiaoke/android-volley 這個非官方的volley項目優化了代碼,據說解決了部分官方volley OOM的問題。後面會分析這個項目具體都解決了些什麼問題。

  1. compile ‘com.mcxiaoke.volley:library:1.0.19-SNAPSHOT’
  2. 或者按照上面的方式,作爲庫項目添加到AS中

使用beyond compare
比較谷歌官方的volley和mcxiaoke/android-volley的區別
注意,因爲兩者格式不一樣,所以不能通過文件的二進制格式比較,全選Compare Contents選擇第三項,Rules-based compration按內容比較,那麼就不會全線都飄紅啦,可以很方便的知道那些文件修改過
最後發現其實沒多大的區別,,,基本一樣,所以使用哪個都可以

至於說會官方Volley會出現OOM那是很久以前的事了,現在不會。
CacheDispacher線程保持了context的引用,導致GC沒有釋放該Activity。可以看到現在最新的Volley的CacheDispacher並沒有引用context,所以這個OOM是不會發生的

使用

這個就不多說了
想粗略的就參考這裏吧 《Android Volley完全解析(一),初識Volley的基本用法》 一系列的文章

基本用法

注意以下地方

  1. mQueue只需要調用一次就行了Volley.newRequestQueue(this);這個方法內部會調用start方法,start方法默認開啓1個緩存線程,4個網絡請求線程。如果new多次了,那麼系統資源肯定最後要被耗盡啊。
  2. mQueue如果能設置爲單例的就最好不過了,就不用頻繁的去創建銷燬線程了,佔用系統資源。Volley內部並沒有使用線程池來管理緩存線程和網絡請求線程。
  3. 如果mQueue沒有設置爲單例模式,那麼onDestroy方法必須調用RequestQueue的stop方法,停止緩存線程和網絡請求線程。這兩個線程內部實現都是while無線循環的,除非調用了stop方法才退出while。想象一下,如果沒有stop,那麼啓動一個activity,如果要做網絡請求,那麼就new一個RequestQueue,就是創建5個線程出來,但是沒有去停止這幾個線程,所以一直累積累積,最後後果不堪設想。
public class MainActivity extends AppCompatActivity {
    private RequestQueue mQueue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mQueue = Volley.newRequestQueue(this);
    }

    @OnClick(R.id.but)
    void onClick() {
        StringRequest stringRequest = new StringRequest("http://www.baidu.com",
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        QDLog.d("onResponse:" + response);
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                QDLog.d("onErrorResponse: " + error.getMessage());
            }
        });
        mQueue.add(stringRequest);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mQueue.stop();
    }
}

post方法添加請求參數,重寫StringRequest的getParams

StringRequest stringRequest = new StringRequest(Method.POST, url,  listener, errorListener) {
    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        Map<String, String> map = new HashMap<String, String>();
        map.put("params1", "value1");
        map.put("params2", "value2");
        return map;
    }
};

加載網絡圖片

提供了三種方式
1. ImageRequest
ImageRequest繼承自Request,所以跟StringRequest等的使用方法差不多,提供了硬盤緩存,同時爲了防止OOM對原圖片進行了縮放處理。但是另一個問題,ImageRequest不適用於listview,gridview等滑動快速,需要頻繁加載圖片的場景,因爲沒有提供內存緩存。這個時候就需要使用ImageLoader咯,相比較ImageRequest,多了內存緩存的功能實現

2. ImageLoader
內部還是採用ImageRequest來實現的,只是添加了一級緩存(內存緩存)而已
下面的系列會介紹ImageRequest和ImageLoader的區別和聯繫

3. NetworkImageView
這個就不說了,NetworkImageView是一個自定義View,它是繼承自ImageView的,具備ImageView控件的所有功能,並且在原生的基礎之上加入了加載網絡圖片的功能

自定義Request

必須實現parseNetworkResponse(解析網絡請求結果)和deliverResponse(分發結果)這兩個方法

public class GsonRequest<T> extends Request<T> {

    private final Listener<T> mListener;

    private Gson mGson;

    private Class<T> mClass;

    public GsonRequest(int method, String url, Class<T> clazz, Listener<T> listener,
            ErrorListener errorListener) {
        super(method, url, errorListener);
        mGson = new Gson();
        mClass = clazz;
        mListener = listener;
    }

    public GsonRequest(String url, Class<T> clazz, Listener<T> listener,
            ErrorListener errorListener) {
        this(Method.GET, url, clazz, listener, errorListener);
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(mGson.fromJson(jsonString, mClass),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(T response) {
        mListener.onResponse(response);
    }

}
發佈了78 篇原創文章 · 獲贊 9 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章