Volley框架的使用(加载网络图片,加载json数据)

  1.Volley 简介 
    1.  下载地址:https://android.googlesource.com/platform/frameworks/volley 
    2.   volley视频:http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded
    3.   它是谷歌在2013年I/O大会上提出来的一套解决 Android与服务器端进行通信的框架
    4.   以前我们安卓端与服务器进行通信的时候一般都是使用 AsyncTask, HttpUrlConnection, HttpClient
        
2.功能介绍

  1.  json,图片等异步下载
  2.  多级别取消请求
  3.  和Activity的生命周期的联动(Activity结束,同时取消所有网络请求)
  4.  网络排序请求
  5.  网络请求优先级处理
  6.  缓存

3. volley的使用

  3.1从服务器获取数据

java 代码


总结
Volley提供了 JsonObjectRequest、 JsonArrayRequest、 StringRequest等 Request形式。

  1. JsonObjectRequest:返回JSON对象。
  2. JsonArrayRequest:返回JsonArray。
  3. StringRequest:返回String,这样可以自己处理数据,更加灵活。
  4. 另外可以继承Request<T>自定义Request。

3.2 图片加载

  1. 使用imageRequst下载图片
  2. 使用imageload下载图片
  3. 使用NetWorkImageView

4.框架详解

流程: Volley.newRequestQueue(),初始化网络请求队列,然后add()消息到RequestQueue,NetworkDispatcher分发消息到NetWork调用HttpStack请求网络,提交本地缓存信息到请求头,NetWork封装HttpStack返回数据,判断是否使用缓存,或者抛出相关的异常。



相关注释
  1. Volley 是一个帮助类 主要负责创建请求队列 并且启动队列消息的循环
  2. HttpStack负责网络解析请求 ,performRequest 返回的是一个Apache的HttpResponse
  3. 注:在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection
  4. NetWork 封装了HttpStack的网络请求,performRequest方法直接返回一个NetWorkResponse 处理了请求异常抛出VolleyError;
  5. NetWorkDispatcher 网络调度(线程池),分发网络请求到NetWork

———————————部分核心代码--------------------------------------

1.RequestQueue.start() 启动缓存调度和网络调度

    public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // Create network dispatchers (and corresponding threads) up to the pool size.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }
</pre><pre name="code" class="java" style="font-size: 14px;"><pre name="code" class="java">1.BaseNetWork   
网络连接任务,@Override    
public NetworkResponse performRequest(Request<?> request) throws VolleyError { 
       long requestStart = SystemClock.elapsedRealtime();       
	   while (true) {           
	   HttpResponse httpResponse = null;           
	   byte[] responseContents = null;            
	   Map<String, String> responseHeaders = new HashMap<String, String>();           
	   try {                // Gather headers.                
	   Map<String, String> headers = new HashMap<String, String>();//请求头信息。               
	   addCacheHeaders(headers, request.getCacheEntry());//添加本地缓存头信息               
	   httpResponse = mHttpStack.performRequest(request, headers);//发出网络请求               
	   StatusLine statusLine = httpResponse.getStatusLine();               
	   int statusCode = statusLine.getStatusCode();//HTTP状态码
                responseHeaders = convertHeaders(httpResponse.getAllHeaders());//解析头信息 
				// Handle cache validation.               
				if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//可以使用缓存数据         
				return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,          
				request.getCacheEntry().data, responseHeaders, true);     
				}
                // Some responses such as 204s do not have content.  We must check.    
				if (httpResponse.getEntity() != null) {//将返回数据 转化为byte数据   
				responseContents = entityToBytes(httpResponse.getEntity());        
        } else {//如果没有返回内容。                 
		// Add 0 byte response as a way of honestly representing a                  
		// no-content request.                 
		responseContents = new byte[0];             
		}
                // if the request is slow, log it.    
				long requestLifetime = SystemClock.elapsedRealtime() - requestStart;      
				//如果请求时间过长 则打印Log               
				logSlowRequests(requestLifetime, request, responseContents, statusLine);
				
                if (statusCode < 200 || statusCode > 299) {//服务器返回异常 则抛出IOException   
				throw new IOException();                
				}                
				return new NetworkResponse(statusCode, responseContents, responseHeaders, false);        
				} catch (SocketTimeoutException e) {//链接超时 尝试重新链接 如果达到尝试次数 则会抛出VolleyError异常,此次请求则结束。    
				attemptRetryOnException("socket", request, new TimeoutError());         
				} catch (ConnectTimeoutException e) {//链接超时 尝试重新链接 如果达到尝试次数 则会抛出VolleyError异常,此次请求则结束。       
				attemptRetryOnException("connection", request, new TimeoutError());         
				} catch (MalformedURLException e) {//Bad URL              
				throw new RuntimeException("Bad URL " + request.getUrl(), e);    
				} catch (IOException e) {           
				int statusCode = 0;                
				NetworkResponse networkResponse = null;           
				if (httpResponse != null) {                  
				statusCode = httpResponse.getStatusLine().getStatusCode();       
				} else {//{//如果没有返回httpResponse,就说明没连接            
				throw new NoConnectionError(e);              
				}              
				VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());              
				if (responseContents != null) {                  
				networkResponse = new NetworkResponse(statusCode, responseContents,responseHeaders, false);              
				if (statusCode == HttpStatus.SC_UNAUTHORIZED ||                          
				statusCode == HttpStatus.SC_FORBIDDEN) {//认证失败异常,重试             
				attemptRetryOnException("auth",request, new AuthFailureError(networkResponse)); 
				} else {//服务器异常                        // TODO: Only throw ServerError for 5xx status codes.                 
				throw new ServerError(networkResponse);                   
				}             
				} else {//网络异常         
				throw new NetworkError(networkResponse);         
				}          
				}        
				}   
				


 
 
<span style="font-family: 微软雅黑;">使用Volley加载JSON数据几种方式</span>
import java. util.Map ;

import org.json.JSONException;
import org. json.JSONObject ;

import android. app.Activity ;
import android. os.Bundle ;

import com. android.volley .AuthFailureError;
import com. android.volley .Request. Method;
import com. android.volley .RequestQueue;
import com. android.volley .Response;
import com. android.volley .Response. ErrorListener;
import com. android.volley .Response. Listener;
import com. android.volley .VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com. android.volley .toolbox. JsonObjectRequest;
import com.android.volley.toolbox.JsonRequest;
import com. android.volley .toolbox. StringRequest;
import com. android.volley .toolbox. Volley;
import com. lb.myvolley .R;
import com. lb.myvolley .commom. Constants;

/***
 * 加载网络数据( json数据)
 * **/
public class StringMainActivity extends Activity {
       private RequestQueue queue;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
             super. onCreate(savedInstanceState) ;
             setContentView(R. layout.activity_main );
             queue = Volley. newRequestQueue(StringMainActivity .this );
             initStringQuest();
             try {
                   initJSONObject();
             } catch (Exception e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace() ;
             }
       }

       /***
       * StringQuest的用法 主要就是进行了以下三步操作:
       *
       * 1. 创建一个RequestQueue对象。
       *
       * 2. 创建一个StringRequest对象。
       *
       * 3. 将StringRequest对象添加到RequestQueue里面。
       * **/
       private void initStringQuest() {
             // 第二步
             StringRequest request = new StringRequest( Method.POST ,
                         Constants.URL_HEAD , new Listener<String> () {
                               @Override
                               public void onResponse(String response) {
                                     System.out .println(response );
                               }
                         }, new ErrorListener() {
                               @Override
                               public void onErrorResponse(VolleyError error) {
                               }
                         }) {

                   // 重写getParams()方法,在这里设置POST参数就可以提交给服务器的参数
                   @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 super .getParams() ;
                   }
             };
             // 第三部
             queue.add( request);
       }

       /****
       * . JsonRequest的用法
       * 类似于StringRequest,JsonRequest也是继承自Request类的,不过由于JsonRequest是一个抽象类
       * ,因此我们无法直接创建它的实例
       * ,那么只能从它的子类入手了。JsonRequest有两个直接的子类,JsonObjectRequest和JsonArrayRequest
       * ,从名字上你应该能就看出它们的区别了吧?一个是用于请求一段JSON数据的,一个是用于请求一段JSON数组的
       * ********/
       private void initJSONObject() throws Exception {
             // JSONObject 用来存放数据提交给服务器
             JSONObject obj = new JSONObject() ;
             obj.put( "key", "value");
             JsonObjectRequest objRequest = new JsonObjectRequest( "", obj,
                         new Listener <JSONObject>() {

                               @Override
                               public void onResponse(JSONObject response) {

                               }
                         }, new Response .ErrorListener() {

                               @Override
                               public void onErrorResponse(VolleyError error) {

                               }
                         });
             queue.add( objRequest);
       }

}


 
 

使用Volley加载网络图片

我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据。Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient,几乎在任何项目的代码中我们都能看到这两个类的身影,使用率非常高。

不过HttpURLConnection和HttpClient的用法还是稍微有些复杂的,如果不进行适当封装的话,很容易就会写出不少重复代码。于是乎,一些Android网络通信框架也就应运而生,比如说AsyncHttpClient,它把HTTP所有的通信细节全部封装在了内部,我们只需要简单调用几行代码就可以完成通信操作了。再比如Universal-Image-Loader,它使得在界面上显示网络图片的操作变得极度简单,开发者不用关心如何从网络上获取图片,也不用关心开启线程、回收图片资源等细节,Universal-Image-Loader已经把一切都做好了。

Android开发团队也是意识到了有必要将HTTP的通信操作再进行简单化,于是在2013年Google I/O大会上推出了一个新的网络通信框架——Volley。Volley可是说是把AsyncHttpClient和Universal-Image-Loader的优点集于了一身,既可以像AsyncHttpClient一样非常简单地进行HTTP通信,也可以像Universal-Image-Loader一样轻松加载网络上的图片。除了简单易用之外,Volley在性能方面也进行了大幅度的调整,它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。
import android. app.Activity ;
import android. graphics.Bitmap ;
import android. graphics.Bitmap .Config;
import android. os.Bundle ;
import android. widget.ImageView ;

import com. android.volley .RequestQueue;
import com. android.volley .Response. ErrorListener;
import com. android.volley .Response. Listener;
import com. android.volley .VolleyError;
import com. android.volley .toolbox. ImageLoader;
import com. android.volley .toolbox. ImageLoader.ImageListener ;
import com. android.volley .toolbox. ImageRequest;
import com. android.volley .toolbox. NetworkImageView;
import com. android.volley .toolbox. Volley;
import com. lb.myvolley .R;
import com. lb.myvolley .utils. BitmapCache;

/****
 * 下载图片
 * *******/
public class ImageActivity extends Activity {
       private RequestQueue queue;
       private ImageView imgView;
       private NetworkImageView networkImageView ;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
             super. onCreate(savedInstanceState) ;
             setContentView(R. layout.activity_image );
             imgView = (ImageView ) findViewById( R.id .imageView1) ;
             queue = Volley. newRequestQueue(ImageActivity .this );
       }

       /**
       * 使用场景,单张图片 步骤 1. 创建一个RequestQueue对象。
       *
       * 2. 创建一个Request对象。
       *
       * 3. 将Request对象添加到RequestQueue里面。
       * **/
       private void initImageRequestQueue() {
             /*****
             * 第一个参数为URL 第二个为Listener <Bitmap>回调 第三第四个参数分别用于指定允许图片最大的宽度和高度
             * 第五个参数用于指定图片的颜色属性,Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性
             * 第六个参数是图片请求失败的回调,这里我们当请求失败时在ImageView中显示一张默认图片
             * */
             ImageRequest request = new ImageRequest( "图片地址" , new Listener<Bitmap>() {

                   @Override
                   public void onResponse(Bitmap response) {
                         // 此处设置图片
                   }
             }, 300, 300, Config. ARGB_8888, new ErrorListener() {

                   @Override
                   public void onErrorResponse(VolleyError error) {

                   }
             });
             queue.add( request);
       }

       /*****
       * 多张图片并可以添加到缓存 步骤 1. 创建一个RequestQueue对象。
       *
       * 2. 创建一个ImageLoader对象。
       *
       * 3. 获取一个ImageListener对象。
       *
       * 4. 调用ImageLoader的get()方法加载网络上的图片。
       * ***/
       private void initImageLoader() {
             ImageLoader loader = new ImageLoader(queue , new BitmapCache());
             // 第一个参数为imageViewK控件,第二个为默认图片,第三个为失败显示的图片
             ImageListener listener = ImageLoader.getImageListener (imgView,
                         R.drawable .ic_launcher, R. drawable.ic_launcher );
             loader.get( "图片地址" , listener );
       }

       /**
       * 最简单的推荐方式 1. 创建一个RequestQueue对象。
       *
       * 2. 创建一个ImageLoader对象。
       *
       * 3. 在布局文件中添加一个NetworkImageView控件。 4. 在代码中获取该控件的实例。
       *
       * 5. 设置要加载的图片地址。
       * ***/
       private void initNetWorkImage() {
             ImageLoader imageLoader = new ImageLoader(queue , new BitmapCache());
             networkImageView=( NetworkImageView) findViewById(R. id.network_image_view );
             //默认显示图片
             networkImageView.setDefaultImageResId( R.drawable .ic_launcher) ;
             //失败后显示的图片
             networkImageView.setErrorImageResId( R.drawable .ic_launcher) ;
             networkImageView.setImageUrl( "https://img-my.csdn.net/uploads/201404/13/1397393290_5765.jpeg" ,
                                     imageLoader);
       }
}



 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值