Android训练课程(Android Training)

使用Volley传输网络数据(Transmitting Network Data Using Volley)

Volley 是一个 HTTP 库,它使得在Android应用程序中操作网络更容易,是重要的,更多快速的。Volley 属于“开放源代码项目”。.

Volley 提供了下列好处:

  • 自动化的网络请求调度安排。 
  • 多并发的网络连接。 
  • 对标准HTTP 透明化的硬盘和内存 响应缓存。   cache coherence.
  • 支持请求的优先级。 
  • 支持终止请求的 API. 你可以终止一个单独的请求,或者终止一些范围内的,或者一定请求周期段的请求。 
  • 轻松的定制化,比如重试和回退。 
  • 强顺序,它使得在网络操作时,更容易的正确处理UI和提取数据的异步。 
  • 调试和跟踪工具。.

Volley擅长的RPC类型(远程过程调用)的操作过去常常应用于填充UI,例如提取一页的搜索结果作为结构化数据。它更容易和其他协议整合,和出色的支持原始字符串,图片和JSON。它为你想要的特性提供内建的支持,Volley 将你从样板的代码中解放处理,使得你将注意力集中在你的业务细节。

Volley 不适合用于 大文件的下载 或者流操作,因为Volley在解析过程中会持有所有的响应内容在内存中。如果要大文件下载操作,考虑是使用其他替代,比如DownloadManager

核心的Volley包开放在AOSP工程下的  frameworks/volley,并且包含了主要的请求调度通道,类似于公共应用事业,在Volley "toolbox."是有效的。最简单的添加Volley到你的项目中的方式是 克隆Volley仓库并且做为你项目中的library项目:

  1. 使用Git克隆Volley仓库,在你的命令提示行下输入下面的内容:
    git clone https://android.googlesource.com/platform/frameworks/volley
  2. 导入下载的源代码到你的项目中,并且作为你的library项目 (如果你使用 Eclipse,更多描述请阅读 Managing Projects from Eclipse with ADT,) 或者编译成一个 .jar 文件.

课程


发送一个简单请求 (Sending a Simple Request
学习如何使用Volley的默认行为发送简单请求,和如何去终止一个请求。 
设置请求队列(Setting Up a RequestQueue
学习如何设置一个请求队列,和如何使用一个单例模式来创建一个和你的App的生命周期一致的请求队列 .
构造一个标准请求(Making a Standard Request
学习如何使用Volley的out-of-the-box请求类型(比如原始字符串,图片,JSON)发送一个请求。 
实现自定义的请求(Implementing a Custom Request
学习如何实现自定义请求。 

发送一个简单请求(Sending a Simple Request)

在一个较高的水平,你使用Volley创建一个请求队列并且传入一个 请求对象 作为参数。请求队列负责管理工作线程来 启动网络操作,读取和写入到缓存,和解析响应。请求执行解析原始响应,Volley小心的分发解析的响应传送到主线程。 

这节课描述了如何使用Volley.newRequestQueue 这个便利的方法来发送一个请求。它为你配置了一个请求队列。你可以通过学习下一课,“设置一个请求队列( Setting Up a RequestQueue)”的内容掌握如何配置请求队列。 

这节课也描述了如何添加一个请求到消息队列,和终止一个请求。 

添加网络访问权限(Add the INTERNET Permission)

要使用 Volley, 你必须在你的manifest文件中添加  android.permission.INTERNET 权限. 没有这个,你的app将不能访问网络。 

使用 newRequestQueue

Volley 提供了一个便利的方法 Volley.newRequestQueue 配置一个消息队列,使用默认值,和启动队列,例如:

final TextView mTextView = (TextView) findViewById(R.id.text);
...

// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";

// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener() {
    @Override
    public void onResponse(String response) {
        // Display the first 500 characters of the response string.
        mTextView.setText("Response is: "+ response.substring(0,500));
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        mTextView.setText("That didn't work!");
    }
});
// Add the request to the RequestQueue.
queue.add(stringRequest);

Volley 总是传递那些解析后的响应到主线程。运行在主线程的好处是非常便利的使用收到的数据去通知UI控件,就像 你可以在你的响应handler里自由的直接修改UI控件,但是类库提供的语义格外的重要,尤其是关联到取消请求时。 

阅读 Setting Up a RequestQueue 章节可以获得更多 设置请求队列的内容,它可以用来替代Volley.newRequestQueue便利的方法。 

发送一个请求(Send a Request)

要发送一个请求,你可以简单的构造一个请求,并使用add() 方法添加到请求队列,像上面描述的那样.一旦你添加了请求,它被通过管道移动,获得服务,和获得原始响应和传递。

当你调用了add() 方法,Volley启动一个缓存处理线程和一个网络分发线程池。当你添加请求到队列中,它被缓存线程获拾取和分类: 如果请求可以从缓存中服务,缓存中的原始响应内容被在缓存进程中解析,并且解析后的响应内容被传递到主线程。如果请求无法从缓存中服务,它将被放置在网络队列中。第一个活动的网络线程从队里中拿到它,处理HTTP传输,在工作线程中解析响应的内容,写入响应内容到缓存,并且发送解析后的响应传递到主线程中。

注意哪些 昂贵的操作,比如阻塞I/O,和解析/解码,都是在工作线程中完成的。你可以在任何线程中添加请求,但是响应总是被传递到主线程中。

图表 1 插图说明一个请求的生命周期:

 

图 1. 请求的生命周期.

中断一个请求(Cancel a Request)

要中断一个请求, 在你的请求对象上 调用 cancel()方法.一旦被中断后,Volley会确保 你的响应处理器 绝对不被调用。实际意义是你可在你的activity中的onStop()方法中中断你的等待中的请求,而且你不会被迫乱丢你的请求处理器,比如检查getActivity() == null ,onSaveInstanceState() 方法是否已经被调用,或者其他自卫性的样板代码。  

要获得这样行为的好处,典型情况下你不得不追踪所有 “飞行中的(in-flight)”请求,以使得在合适的时机去终止它。这有一个更简单的方法: 你可以为每一个请求关联一个 标签对象。你可以使用这个标签来提供可被中断请求的范围。比如,你可以使用 Activity对象 标记你所有的请求,并且在 onStop() 时调用  requestQueue.cancelAll(this) 。同样的,你可以 在一个ViewPager选项卡中,使用他们各自的 选项卡对象 标记 它们自己的所有的 缩略图 请求,并在切换时触发终止操作,以确保 新的选项卡对象不会被 其他选项卡的请求 所持有。

下面是一个使用 字符串值作为标签 的示例: 

  1. 定义你的标签并且添加到你的请求上。 
    public static final String TAG = "MyTag";
    StringRequest stringRequest; // Assume this exists.
    RequestQueue mRequestQueue;  // Assume this exists.
    
    // Set the tag on the request.
    stringRequest.setTag(TAG);
    
    // Add the request to the RequestQueue.
    mRequestQueue.add(stringRequest);
  2. 在你的 activity的 onStop() 方法中, 终止所有标记过这个标签的请求。 
    @Override
    protected void onStop () {
        super.onStop();
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(TAG);
        }
    }
    

当调用终止请求时要非常小心。如果你 依赖 你的响应处理器,以变动一个状态或者踢开一些步骤,你需要记得这些。再次强调,在终止后相应处理绝不会被调用。   

设置一个请求队列(Setting Up a RequestQueue)

上节课展示了如何使用 Volley.newRequestQueue 这个便利的方法来设置一个请求队列,以获得Volley提供的默认行为的好处。这节课教你通过明确的几个步骤来创建一个请求队列,使得你可以定制它。 

这节课也描述一个推荐的实践方式,使用单例模式创建一个请求队列,这个请求队列会持续整个App的生命周期。

设置一个网络和缓存(Set Up a Network and Cache)

一个请求队列要完成它自己的工作需要两样东西: 一个 network(网络) 对象处理请求的传输,和一个 cache(缓存)对象来处理缓存。在Volley 工具盒 中已经有了里那两个标准的可用的实现: DiskBasedCache提供了一个 “每响应单文件(one-file-per-response)” 的缓存并在内存中建立索引; BasicNetwork对象提供了以 你自己选择的AndroidHttpClient 或 HttpURLConnection 对象 为基础的网络传输。

BasicNetwork 是Volley的默认 network(网络) 实现。一个 BasicNetwork 对象必须先被  使用HTTP客户端 来初始化后才能连接网络。比较有代表性的是AndroidHttpClient or HttpURLConnection:

要创建一个可运行在Android全版本的应用,你可用检查Android硬件设备上运行的Android系统的版本号,以做出选择是HTTP 客户端,比如: 

HttpStack stack;
...
// If the device is running a version >= Gingerbread...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
    // ...use HttpURLConnection for stack.
} else {
    // ...use AndroidHttpClient for stack.
}
Network network = new BasicNetwork(stack);

这个代码片段展示了设置请求队列的步骤: 

RequestQueue mRequestQueue;

// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap

// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());

// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);

// Start the queue
mRequestQueue.start();

String url ="http://www.myurl.com";

// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
        new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // Do something with the response
    }
},
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // Handle error
    }
});

// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
...

如果你仅仅需要构建单次的请求,并且不想离开线程池的范围,你可用创建在任何地方创建请求队列,和在收到响应或者错误后调用stop()方法,使用Volley.newRequestQueue()的方法可参阅 Sending a Simple Request。但是更多一般的使用情形是 使用单例模式创建请求队列并且让它和你的应用的生命周期一致,更多描述在下一章节。

使用单例模式(Use a Singleton Pattern)

如果你的应用需要经常访问网络,那么配置一个单例模式的请求队列并保持在app的整个生命周期的方式是非常有效率的。你可以有多种方式这样实现。推荐的方式是实现一个单例类来封装请求队列和其他的Volley功能方法/函数。其他的实现方式比如实现 Applicaton的子类并在Application.onCreate()方法中配置请求队列,这样的方式现在是被劝阻的;一个静态的单例能够以模块化的方式提供同样的功能。

一个关键概念是请求队列必须使用Application的context对象来初始化,而不时 Activity的context.这样确保请求队列会持续在整个app的生命周期,而在activity的context的实现会在activity被重新创建时被创建多次(比如,当用户旋转了屏幕就会重新创建activity)。

下面是一个实现了单例模式的类的示例,它提供了请求队列和图片下载器(ImageLoader)的功能: 

private static MySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;

    private MySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();

        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

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

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

    public static synchronized MySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }
}

下面是使用单例类处理请求队列操作的示例: 

// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
    getRequestQueue();
...

// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);

(全文完结)

原文地址:https://www.cnblogs.com/vir56k/p/4707351.html