volley建立標準的網路請求(Making a Standard Request)

銳湃發表於2015-08-12

編寫:kesenhoo - 原文:http://developer.android.com/training/volley/request.html

這一課會介紹如何使用Volley支援的常用請求型別:

  • StringRequest。指定一個URL並在相應回撥中接受一個原始的raw string資料。請參考前一課的示例。
  • ImageRequest。指定一個URL並在相應回撥中接受一個image。
  • JsonObjectRequestJsonArrayRequest (均為JsonRequest的子類)。指定一個URL並在相應回撥中獲取到一個JSON物件或者JSON陣列。

如果你需要的是上面演示的請求型別,那麼你應該不需要自己實現一個自定義的請求。這節課會演示如何使用那些標準的請求型別。關於如何實現自定義的請求,請看下一課:實現自定義的請求

1)Request an Image

Volley為請求圖片提供瞭如下的類。這些類依次有著依賴關係,用來支援在不同的層級進行圖片處理:

  • ImageRequest - 一個封裝好的,用來處理URL請求圖片並且返回一張decode好的bitmap的類。它同樣提供了一些簡便的介面方法,例如指定一個大小進行重新裁剪。它的主要好處是Volley會確保類似decode,resize等耗時的操作執行在工作執行緒中。

  • ImageLoader - 一個用來處理載入與快取從網路上獲取到的圖片的幫助類。ImageLoader是管理協調大量的ImageRequest的類。例如,在ListView中需要顯示大量縮圖的時候。ImageLoader為通常的Volley cache提供了更加前瞻的記憶體快取,這個快取對於防止圖片抖動非常有用。。這還使得能夠在避免阻擋或者延遲主執行緒的前提下在快取中能夠被Hit到。ImageLoader還能夠實現響應聯合Coalescing,每一個響應回撥裡面都可以設定bitmap到view上面。聯合Coalescing使得能夠同時提交多個響應,這提升了效能。

  • NetworkImageView - 在ImageLoader的基礎上建立,替換ImageView進行使用。對於需要對ImageView設定網路圖片的情況下使用很有效。NetworkImageView同樣可以在view被detached的時候取消pending的請求。

1.1)Use ImageRequest

下面是一個使用ImageRequest的示例。它會獲取指定URL的image並顯示到app上。裡面演示的RequestQueue是通過上一課提到的單例類實現的。

ImageView mImageView;
String url = "http://i.imgur.com/7spzG.png";
mImageView = (ImageView) findViewById(R.id.myImage);
...

// Retrieves an image specified by the URL, displays it in the UI.
ImageRequest request = new ImageRequest(url,
    new Response.Listener() {
        @Override
        public void onResponse(Bitmap bitmap) {
            mImageView.setImageBitmap(bitmap);
        }
    }, 0, 0, null,
    new Response.ErrorListener() {
        public void onErrorResponse(VolleyError error) {
            mImageView.setImageResource(R.drawable.image_load_error);
        }
    });
// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(request);

1.2)Use ImageLoader and NetworkImageView

你可以使用ImageLoader與NetworkImageView用來處理類似ListView等大量顯示圖片的情況。在你的layout XML檔案中,你可以使用NetworkImageView來替代通常的ImageView, 例如:

<com.android.volley.toolbox.NetworkImageView
        android:id="@+id/networkImageView"
        android:layout_width="150dp"
        android:layout_height="170dp"
        android:layout_centerHorizontal="true" />

你可以使用ImageLoader來顯示一張圖片,例如:

ImageLoader mImageLoader;
ImageView mImageView;
// The URL for the image that is being loaded.
private static final String IMAGE_URL =
    "http://developer.android.com/images/training/system-ui.png";
...
mImageView = (ImageView) findViewById(R.id.regularImageView);

// Get the ImageLoader through your singleton class.
mImageLoader = MySingleton.getInstance(this).getImageLoader();
mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
         R.drawable.def_image, R.drawable.err_image));

然而,如果你要做得是為ImageView進行圖片設定,你可以使用NetworkImageView來實現,例如:

ImageLoader mImageLoader;
NetworkImageView mNetworkImageView;
private static final String IMAGE_URL =
    "http://developer.android.com/images/training/system-ui.png";
...

// Get the NetworkImageView that will display the image.
mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);

// Get the ImageLoader through your singleton class.
mImageLoader = MySingleton.getInstance(this).getImageLoader();

// Set the URL of the image that should be loaded into this view, and
// specify the ImageLoader that will be used to make the request.
mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);

上面的程式碼是通過前一節課的單例模式來實現訪問到RequestQueue與ImageLoader的。之所以這樣做得原因是:對於ImageLoader(一個用來處理載入與快取圖片的幫助類)來說,單例模式可以避免旋轉所帶來的抖動。使用單例模式可以使得bitmap的快取與activity的生命週期無關。如果你在activity中建立ImageLoader,這個ImageLoader有可能會在手機進行旋轉的時候被重新建立。這可能會導致抖動。

1.3)Example LRU cache

Volley工具箱中提供了通過DiskBasedCache實現的一種標準快取。這個類能夠快取檔案到磁碟的制定目錄。但是為了使用ImageLoader,你應該提供一個自定義的記憶體LRC快取,這個快取需要實現ImageLoader.ImageCache的介面。你可能想把你的快取設定成一個單例。關於更多的有關內容,請參考建立請求佇列Setting Up a RequestQueue.

下面是一個記憶體LRU Cache的例項。它繼承自LruCache並實現了ImageLoader.ImageCache的介面:

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.DisplayMetrics;
import com.android.volley.toolbox.ImageLoader.ImageCache;

public class LruBitmapCache extends LruCache<String, Bitmap>
        implements ImageCache {

    public LruBitmapCache(int maxSize) {
        super(maxSize);
    }

    public LruBitmapCache(Context ctx) {
        this(getCacheSize(ctx));
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight();
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }

    // Returns a cache size equal to approximately three screens worth of images.
    public static int getCacheSize(Context ctx) {
        final DisplayMetrics displayMetrics = ctx.getResources().
                getDisplayMetrics();
        final int screenWidth = displayMetrics.widthPixels;
        final int screenHeight = displayMetrics.heightPixels;
        // 4 bytes per pixel
        final int screenBytes = screenWidth * screenHeight * 4;

        return screenBytes * 3;
    }
}

下面是如何初始化ImageLoader並使用cache的例項:

RequestQueue mRequestQueue; // assume this exists.
ImageLoader mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache(LruBitmapCache.getCacheSize()));

2)Request JSON

Volley提供了以下的類用來執行JSON請求:

  • JsonArrayRequest - 一個為了獲取JSONArray返回資料的請求。
  • JsonObjectRequest - 一個為了獲取JSONObject返回資料的請求。允許把一個JSONObject作為請求引數。

這兩個類都是繼承自JsonRequest的。你可以使用類似的方法來處理這兩種型別的請求。如下演示瞭如果獲取一個JSON feed並顯示到UI上:

TextView mTxtDisplay;
ImageView mImageView;
mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);
String url = "http://my-json-feed";

JsonObjectRequest jsObjRequest = new JsonObjectRequest
        (Request.Method.GET, url, null, new Response.Listener() {

    @Override
    public void onResponse(JSONObject response) {
        mTxtDisplay.setText("Response: " + response.toString());
    }
}, new Response.ErrorListener() {

    @Override
    public void onErrorResponse(VolleyError error) {
        // TODO Auto-generated method stub

    }
});

// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

關於基於Gson實現一個自定義的JSON請求物件,請參考下一節課:實現一個自定義的請求Implementing a Custom Request.

轉自:http://hukai.me/android-training-course-in-chinese/connectivity/volley/request.html

相關文章