Volley Lesson 3 -Making a Standard Request(译)

原文链接:http://developer.android.com/training/volley/request.html

该文将介绍如何使用常见的Volley支持的请求类型:

  • StringRequest:定义一个URL,在response中接收原始的字符串。可以参见之前的Setting Up a Request Queue。
  • ImageRequest:定义一个URL,在response中接收图片
  • JsonObjectReqeust/JsonArrayRequest:都是JsonReqeust的子类,接收Json object或者array。

如果我们的数据类型也是上面的几种之一的话,那么我们是不需要自己实现自己的request的。如果需要接收自己特定格式的Request的话,可以参考下一节课程。

Request an Image

Volley提供了以下的类用来请求图像。这些类一次提供了不同级别上的图片处理能力。

  • ImageReqeust:一个请求可以用来访问特定URL的图片并且返回一个解码之后的bitmap。并且也提供了方便的特性比如缩放至一个特定的尺寸。其中最大的好处在于Volley的线程调度保证了耗时的图片操作,比如decoding,比如resizing都发生在worker线程中。
  • ImageLoader:是一个工具类用来加载和缓存URL的图片。ImageLoader在处理大量的ImageRequest的时候很有用,比如:当我们需要在ListView中放置很多的缩放图片,ImageLoader提供了in-memory级别的cache来作为Volley的前置cache,这样就避免了很多闪烁的现象。这样也使得我们在cache命中,而且又使用disk I/O的时候可以不阻塞main线程。ImageLoader也会负责一些聚合操作,如果没有ImageLoader,那么大部分的response handler都要负责在view上设置图片等操作。ImageLoader的聚合操作使得同时我们可以同时派发得以实现。
  • NetworkImageView:基于ImageLoader构建,当图片需要从网络URL中获取的时候,用来代替ImageView。如果使用NewworkImageView的话,当NetworkImageView从视图上剥离的时候回自动的取消等待的请求。

Use ImageRequest

一个使用ImageRequest的例子,其中使用单利调用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);

Use ImageLoader and NetworkImageView

在需要展示大量的图片的时候,使用ImageLoader或者NetworkImageView会拥有更高的效率,比如ListView。如果使用NetworkImageView,可以像如下使用:

<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));

使用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);

要注意的是,以上的ImageLoader都是使用了单例模式,使得在整个APP的生命周期中都可以直接使用。特别注意的是,这种设计模式在使用ImageLoader的时候特别需要重视,因为ImageLoader使用了内存缓存,可以减少图片旋转时候闪烁现象的发生。否则如果我们是在activity中设置ImageLoader,那么当用户每次旋转屏幕的时候,ImageLoader都会重构,就会导致严重的闪烁现象。

Example LRU cache

Volley工具类提供了一个标准的cache实现:DiskBasedCache。该类会在磁盘中特定文件夹中直接缓存文件。但是实用ImageLoader的时候,我们需要自己创建一个内存cache,该cache要实现ImageLaoder.ImageCache接口。

以下是一个in-memory的LruBitmapCache例子,该类继承了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;
    }
}

如下使用:

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

Request JSON

Volley提供了以下两个类实现JSON请求:

  • JsonArrayRequest:请求数组
  • JsonObjectRequest:获取JSON Object。可以有一个JSONObject通过request body传递请求。

两个类都是基于JsonRequest实现,以下是个例子。

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);

 

 

 

 

About: happyhls


发表评论

电子邮件地址不会被公开。 必填项已用*标注