Maison  >  Article  >  Java  >  Développement Android : explication détaillée de l'utilisation spécifique de Volley

Développement Android : explication détaillée de l'utilisation spécifique de Volley

黄舟
黄舟original
2017-03-10 09:26:491555parcourir

0. Avant-propos

Principalement fourni par le système Android HttpURLConnection et HttpClient sont utilisés pour la communication réseau, mais si ne l'encapsule pas Il est très simple d'écrire du code en double. Par conséquent, certains cadres de communication réseau Android ont vu le jour, Volley est l'un des meilleurs, VolleyNon seulement HTTP communiquer, mais vous pouvez aussi facilement charger des images sur le réseau. L'intention initiale de Volley est que est très approprié pour les opérations réseau avec une petite quantité de données mais des communications fréquentes , et pour de grandes quantités de données Pour les opérations réseau, telles que le téléchargement de fichiers, etc., les performances de Volley seront très mauvaises. Les raisons se résument ainsi :

(1)Réseau de Volley demander les valeurs par défaut du pool de threads pour 4. Par conséquent, seules 4 requêtes peuvent être effectuées simultanément (plus de files d'attente), et est facilement remplacé par 4 les plus volumineuses. La tâche de téléchargement du fichier bloque les autres requêtes . parseNetWorkResponse() La méthode

renvoie

byte[] type et les données transférées doivent être lues dans la mémoire. Si le fichier est trop volumineux, il est facile de provoquer un MOO. 1.Utilisation de base du Volley

1.1 HTTP GETDemande

Tout d’abord, importez le Package du pot Volley's dans

AS

. Le constructeur de

StringRequest doit passer trois paramètres, le premier est le URL adresse , les deuxièmes / trois paramètres sont des rappels pour le succès de la réponse du serveur

RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest_get = 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);
            }
  });
mQueue.add(stringRequest);
/

échec. En cas de succès, convertissez le code html renvoyé en String et imprimez le log . 1.2 HTTP POSTDemande


当发出POST请求的时候,Volley会尝试调用StringRequest的父类中的getParams()方法来获取POST参数,因此我们需要在StringRequest中重写getParams()方法,设置POST参数即可。


1.3  JsonRequest

StringRequest一样,JsonRequest也是继承自Request类的 JsonRequest是一个抽象类,有两个子类JsonObjectRequestJsonArrayRequest,前者用于请求一段JSON数据的,后者用于请求一段JSON数组。下面是使用前者进行一段Json请求的范例代码。


//队列初始化以及request加入队列略
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, 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);  
            }  
});



1.4  ImageRequest

Volley支持对图片的加载,因为ImageRequest也是继承自Request类,因此用法也大同小异。下面直接传入图片url,返回数据后内部解析为bitmap,最后设置给ImageView。否则设置默认图片。

ImageRequest imageRequest = new ImageRequest(url_image,  
        new Response.Listener<Bitmap>() {  
            @Override  
            public void onResponse(Bitmap response) {  
                imageView.setImageBitmap(response);  
            }  
        }, 0, 0, Config.RGB_565, new Response.ErrorListener() {  
            @Override  
            public void onErrorResponse(VolleyError error) {  
                imageView.setImageResource(R.drawable.default_image);  
            }  
});

需要注意的是,第三/四个参数用于指定允许图片最大的宽/,若网络图片的实际宽高大于该设定值,则会对图片进行压缩,指定成0的话就表示不进行压缩。第五个参数用于指定图片的颜色属性Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而RGB_565则表示每个图片像素占据2个字节大小。不过这种加载图片的方式并不被推荐,因为下面有更好的。



1.5  ImageLoader

ImageLoader基于ImageRequest实现,并且更加智能,多出了帮图片缓存的功能,还可以过滤掉重复的请求链接。但是ImageLoader已经不再继承自Request类。

//mQueue初始化略
ImageLoader imageLoader = new ImageLoader(mQueue, new BitmapCache());
ImageListener listener = ImageLoader.getImageListener(imageView,  R.drawable.default_image, 
R.drawable.failed_image);  
imageLoader.get(url_image, listener, 200, 200);  //限制最大宽高
public class BitmapCache implements ImageCache { 
    //内部使用LRU实现 
    private LruCache<String, Bitmap> mCache;  
public BitmapCache() {  
	   //缓存图片的大小设置为10M
        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);  
    }  
}


第二行构造一个ImageLoader对象,其中第二个参数是一个ImageCache对象,参数二为自定义的用户缓存的类BitmapCache,该类继承了ImageCache。第三行获取一个ImageListener对象,传入参数比较简单,看名字就知道了。第四行调用ImageLoaderget()方法来加载图片。

 

1.6  NetworkImageView

这是第三种加载图片的方式,相对来说也是被用的比较多的方式。NetworkImageView继承自ImageView的,在原生的基础之上加入了加载网络图片的功能。用法仍旧是先创建一个RequestQueue对象和一个ImageLoader对象。接下来是在xml中定义我们的NetworkImageView,宽高表示裁剪到此宽高,wrap_content表示不裁剪。

<com.android.volley.toolbox.NetworkImageView   
        android:id="@+id/network_image_view"  
        android:layout_width="100dp"  
        android:layout_height="100dp"/>

Activity中获取到NetworkImageView实例后,就可以调用它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法来分别设置加载时显示的图片,加载失败时显示的图片,以及目标图片的URL地址。

networkImageView.setDefaultImageResId(R.drawable.default_image);  
networkImageView.setErrorImageResId(R.drawable.failed_image);  
networkImageView.setImageUrl(url_image,imageLoader);


2.  自定义Request

在网络上传输的数据常用到XMLJSON格式,那么如果想要请求一条XML/JSON格式的数据就需要拓展我们的Volley

 

2. 1  XMLRequest

public class StringRequest extends Request<String> {  
    private final Listener<String> mListener;  
    public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) {  
        super(method, url, errorListener);  
        mListener = listener;  
    }  
    public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {  
        this(Method.GET, url, listener, errorListener);  
    }  
  
    @Override  
    protected void deliverResponse(String response) {  
        mListener.onResponse(response);  
    }  
  
    @Override  
    protected Response<String> parseNetworkResponse(NetworkResponse response) {  
        String parsed;  
        try {  
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));  
        } catch (UnsupportedEncodingException e) {  
            parsed = new String(response.data);  
        }  
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));  
    }  
}

拓展之前先要看一下原有的Request的子类是如何实现的,上面以StringRequest为例。StringRequest中提供了两个有参的构造函数,参数包括请求类型,请求地址,以及响应回调等,在构造函数中一定要调用super()方法将这几个参数传给父类,因为HTTP的请求和响应都是在父类中处理的。

由于Request类中的deliverResponse()parseNetworkResponse()是两个抽象方法,因此StringRequest中对这两个方法进行了实现。前者调用了mListener中的onResponse()方法,并将response内容传入即完成了将服务器响应的数据进行回调。后者对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponsedata变量中(前言中在Volley为什么不适合大文件下载就讲到了),这里将数据取出然后组装成一个String,并传入Responsesuccess()方法中。

在了解了StringRequest之后,我们自定义实现我们的XMLRequest

public class XMLRequest extends Request<XmlPullParser> {  
    private final Listener<XmlPullParser> mListener;  
    public XMLRequest(int method, String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {  
        super(method, url, errorListener);  
        mListener = listener;  
    }  
  
    public XMLRequest(String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {  
        this(Method.GET, url, listener, errorListener);  
    }  
  
    @Override  
    protected void deliverResponse(XmlPullParser response) {  
        mListener.onResponse(response);  
    }  

    @Override  
    protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) {  
        try {  
		  //先转为字符串
            String xmlString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));  
		  //重点在于解析xml
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();  
            XmlPullParser xmlPullParser = factory.newPullParser();  
            xmlPullParser.setInput(new StringReader(xmlString));
		  //返回XmlPullParser实例
            return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response));  
        } catch (UnsupportedEncodingException e) {  
            return Response.error(new ParseError(e));  
        } catch (XmlPullParserException e) {  
            return Response.error(new ParseError(e));  
        }  
    }    
}  

//使用我们的XMLRequest
XMLRequest xmlRequest = new XMLRequest( url_xml, new Response.Listener<XmlPullParser>() {  
            @Override  
            public void onResponse(XmlPullParser response) {  
                try {  
                    int eventType = response.getEventType();  
                    while (eventType != XmlPullParser.END_DOCUMENT) {  
                        switch (eventType) {  
                        case XmlPullParser.START_TAG:  
                            String nodeName = response.getName();  
                            if (WANTED_TAG.equals(nodeName)) {  
                                String pName = response.getAttributeValue(0);  
                                Log.d("TAG", "pName is " + pName);  
                            }  
                            break;  
                        }  
                        eventType = response.next();  
                    }  
                } catch (XmlPullParserException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }, new Response.ErrorListener() {  
            @Override  
            public void onErrorResponse(VolleyError error) {  
                Log.e("TAG", error.getMessage(), error);  
            }  
        });


2. 2  GsonRequest

用过Gson的都知道Gson解析有多方便,这里可以把VolleyGson结合在一起吗?当然可以。重写代码基本上大同小异。前提是先导入Gson的jar包

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));
		  //结合Gson解析  
            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);  
}  
}  

//使用我们的GsonRequest
GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>(url_json,YourClass.class,  
        new Response.Listener<Weather>() {  
            @Override  
            public void onResponse(YourClass obj) {  
			//这里获得obj对应的json中的数据
            }  
        }, new Response.ErrorListener() {  
            @Override  
            public void onErrorResponse(VolleyError error) {  
                Log.e("TAG", error.getMessage(), error);  
            }  
        });




Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn