一、简介
1.下载和视频
1.下载地址:https://github.com/mcxiaoke/android-volley
2.volley视频:http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded
3.它是谷歌在2013年I/O大会上提出来的一套解决 Android与服务器端进行通信的框架
2.android提供的两种方式来进行HTTP通信
HttpClicent 建议在2.3之前的版本使用,bug少
HttpUrlConnection建议2.3以后使用,他api简单,体积小,非常适合移动项目这种轻量级的项目,压缩和缓存机制可以有效的减少网络访问的流量,在提升速度和省电方面也起到了很大的作用
在 Froyo(2.2) 之前,HttpURLConnection 有个重大 Bug,调用 close() 函数会影响连接池,导致连接复用失效,所以在 Froyo 之前使用 HttpURLConnection 需要关闭 keepAlive
3.Google推荐的用法
如果一个App需要频繁的网络通信的话,建立多个RequestQueue是件很奇怪的事儿(谁会因为临时有飞机要在海上起飞就去新建一艘航母呢,这得多有钱啊),所以Google推荐我们只实例化一个RequestQueue来应付频繁的Http通信,当然,要保证队列的寿命和App一样长。如何实现呢?Google又说了,不推荐在App的Application.onCretae()方法中实例化一个RequestQueue(不过确实是个简单的方法哈),最好是建立一个单例模式的类,并把所有我们需要用到的Volley的瓶瓶罐罐都放进去,这样显得更模块化。
4.缺点:不适合大文件的上传和下载
二、功能
json数据加载,图片异步下载
缓存功能
和Activity的生命周期联动(Activity结束以后可以取消所有网络请求)
多级别任务取消
网络请求排序
三、Http请求
Request请求
1.StringRequest(重点)
2.JsonObjectRequest(了解)
3.JsonArrayRequest(了解)
4.自定义Request(了解)
使用方式
第一步创建请求队列
这里拿到的RequestQueue是一个请求队列对象,它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,建议使用封装单利模式
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
第二步创建请求
GET------>请求:StringRequest request = new StringRequest(url, listener, errorListener)
String url 加载数据网址
Listener<String> listener(接口) 数据加载成功回调方法
ErrorListener errorListener(接口) 数据加载失败回调方法
POST请求
当发出POST请求的时候,Volley会尝试调用StringRequest的父类——Request中的getParams()方法来获取POST参数
在StringRequest的匿名类中重写getParams()方法,在这里设置POST参数就可以了
StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener) {
@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 map;
}
};
第三步设置tag
request.setTag(this)
Object object 设置取消的标识
一般使用Activity或者fragment作为标识
第四步添加进请求队列
queue.addRequest(request)
第五步取消请求
重写Activity或者fragment的 onStop()方法
@Override
protected void onStop() {
super.onStop();
queue.cancelAll(this);
}
其他
设置请求(HTTP headers)
有时候需要给HTTP请求添加额外的头信息,一个常用的例子是添加 “Authorization”到HTTP 请求的头信息。Volley请求类提供了一个 getHeaers()的方法,重载这个方法可以自定义HTTP 的头信息。
JsonObjectRequest request = new JsonObjectRequest(URL, new JSONObject(params),
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// handle response
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// handle error
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("CUSTOM_HEADER", "qian'feng");
headers.put("ANOTHER_CUSTOM_HEADER", "qianfeng");
return headers;
}
};
使用Cookies
Volley中没有直接的API来设置cookies,Volley的设计理念就是提供干净、简洁的API来实现RESTful HTTP请求,不提供设置cookies是合理的。 下面是修改后的ApplicationController类,这个类修改了getRequestQueue()方法,包含了 设置cookie方法,这些修改还是有些粗糙
private DefaultHttpClient mHttpClient;
public RequestQueue getRequestQueue() {
// lazy initialize the request queue, the queue instance will be
// created when it is accessed for the first time
if (mRequestQueue == null) {
// Create an instance of the Http client.
// We need this in order to access the cookie store
mHttpClient = new DefaultHttpClient();
// create the request queue
mRequestQueue = Volley.newRequestQueue(this, new HttpClientStack(mHttpClient));
}
return mRequestQueue;
}
/**
* Method to set a cookie
*/
public void setCookie() {
CookieStore cs = mHttpClient.getCookieStore();
// create a cookie
cs.addCookie(new BasicClientCookie2("cookie", "spooky"));
}
// add the cookie before adding the request to the queue
setCookie();
// add the request to the queue
mRequestQueue.add(request);
Cookies用在程序设计中是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。当你浏览某网站时,由Web服务器置于你硬盘上的一个非常小的文本文件,它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。当你再次来到该网站时,网站通过读取Cookies,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。从本质上讲,它可以看作是你的身份证
类似第三方开源库
1.android-async-http
它把HTTP所有的通信细节全部封装在了内部,我们只需要简单调用几行代码就可以完成通信操作了,避免重复代码
1.处理异步Http请求,并通过匿名内部类处理回调结果
2.Http请求均位于非UI线程,不会阻塞UI操作
3.通过线程池处理并发请求
4.处理文件上传、下载
5.响应结果自动打包JSON格式
6.二进制文件下载(如图片)
7.自动处理连接断开时请求重连
8.持久化存储cooki,将cooki保存到你应用的SharedPreferences
2.android-lite-http https://github.com/litesuits/android-lite-http
3.okhttp https://github.com/square/okhttp
四、图片异步下载
1.Volley-image
ImageRequest(了解)
ImageLoader(重点)
NetworkImageView(重点)
4.图片内存缓存处理(Lrucache)
2.使用方式
ImageRequest
参照Request的使用方式
ImageLoader(代码参照案例)
创建一个RequestQueue对象
创建一个ImageLoader对象
获取一个ImageListener对象
调用ImageLoader的get()方法加载网络上的图片
NetworkImageView(代码参照案例)
创建一个RequestQueue对象
创建一个ImageLoader对象
在布局文件中添加一个NetworkImageView控件。
在代码中获取该控件的实例。
设置要加载的图片地址。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private LinearLayout mOperation;
private TextView mContent;
private ImageView mImage;
private RequestQueue mQueue;
LruCache<String,Bitmap> lruCache = new LruCache<>(1024*1025*5);
private NetworkImageView mImage2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mOperation = (LinearLayout)findViewById(R.id.operation);
mContent = (TextView)findViewById(R.id.text);
mImage = (ImageView)findViewById(R.id.image);
mImage2 = (NetworkImageView)findViewById(R.id.image2);
setAllClick();
//1、创建请求队列
mQueue = Volley.newRequestQueue(this);
}
private void loadImage() {
String url ="http://fmn.rrfmn.com/fmn060/20150204/0425/large_JV8E_4c30000177a5125f.jpg";
//2、创建loader 缓存
ImageLoader.ImageCache cache =new ImageLoader.ImageCache() {
@Override
public Bitmap getBitmap(String url) {
return lruCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
lruCache.put(url,bitmap);
}
};
//1、创建ImageLoader
ImageLoader loader = new ImageLoader(mQueue,cache);
//3、加载图片
loader.get(url,ImageLoader.getImageListener(mImage,R.mipmap.ic_launcher,R.mipmap.ic_launcher));
//4、netWorkImageView
mImage2.setImageUrl("http://img5.imgtn.bdimg.com/it/u=2685634614,3437522115&fm=21&gp=0.jpg",loader);
}
private void setAllClick() {
/**
* StringRequest
*/
mOperation.getChildAt(0).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// stringRequestGet();
stringRequestPost();
}
});
/**
* JsonObjectRequest
*/
mOperation.getChildAt(1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
jsonObjRequest();
}
});
/**
* MyRequest
*/
mOperation.getChildAt(2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
objectRequest();
}
});
/**
* ImageLoad
*/
mOperation.getChildAt(3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadImage();
}
});
}
private void objectRequest(){
String url = "http://139.129.19.51/story/index.php/home/Interface/login";
ObjectRequest<LoginResult> request = new ObjectRequest<LoginResult>(Request.Method.POST, url, LoginResult.class, new Response.Listener<LoginResult>() {
@Override
public void onResponse(LoginResult response) {
if(response!=null){
mContent.setText(response.getMsg());
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}){
/**
* 注意::::!!!!! 参数
* @return
* @throws AuthFailureError
*/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String,String> params = new HashMap<>();
params.put("username","admin");
params.put("password","123456");
return params;
}
};
mQueue.add(request);
}
/**
* String加载GET
*/
private void stringRequestGet() {
//2、创建请求
String url = "http://www.baidu.com";
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//回调主线程
mContent.setText(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
//选择性,添加标记,用于取消网络
request.setTag(this);
//3、添加请求
mQueue.add(request);
}
/**
* String加载POST
*/
private void stringRequestPost() {
//2、创建请求
String url = "http://139.129.19.51/story/index.php/home/Interface/login";
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//回调主线程
mContent.setText(response);
Gson gson = new Gson();
LoginResult loginResult = gson.fromJson(response, LoginResult.class);
Log.i(TAG,loginResult.getData().getNickname());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG,error.getMessage());
}
}){
/**
* 注意::::!!!!! 参数
* @return
* @throws AuthFailureError
*/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String,String> params = new HashMap<>();
params.put("username","admin");
params.put("password","123456");
return params;
}
};
//选择性,添加标记,用于取消网络
request.setTag(this);
//3、添加请求
mQueue.add(request);
}
/**
* 提交JSON 请求
*/
private void jsonObjRequest(){
String url = "http://139.129.19.51/story/index.php/home/Interface/loginJson";
//注意传参 为 json串
HashMap<String,String> params = new HashMap<>();
params.put("username","admin");
params.put("password","123456");
JSONObject jsonObj = new JSONObject(params);
String body =jsonObj.toString();
Log.i(TAG,body);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, body, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
if(response!=null){
int result = response.optInt("result");
if(result==1){
String msg = response.optString("msg");
mContent.setText(msg);
}else{
mContent.setText("登录失败!!!!");
}
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
request.setTag(this);
mQueue.add(request);
}
@Override
protected void onDestroy() {
//取消网络请求
mQueue.cancelAll(this);
super.onDestroy();
}
}
Gson
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import java.io.UnsupportedEncodingException;
/**
* Created by keven on 16/3/14.
*/
public class ObjectRequest<T> extends Request<T> {
private final Response.Listener success; //成功监听
private final Class<T> cls; //传递类型,通过类型转换返回的参数
public ObjectRequest(int method, String url, Class<T> cls, Response.Listener success, Response.ErrorListener listener) {
super(method, url, listener);
this.success = success;
this.cls = cls;
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
String result = null;
try {
//处理返回的数据
result = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
//Gson 转换 类型
Gson gson = new Gson();
T t = gson.fromJson(result, cls);
return Response.success(t,HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new VolleyError(e));
}
}
@Override
protected void deliverResponse(T response) {
if(success!=null){
success.onResponse(response);
}
}
}
bean就不贴了
/**
* result : 1
* msg : 登录成功
* data : {"id":"467","username":"admin","userpass":"MTRlMWI2MDBiMWZkNTc5ZjQ3NDMzYjg4ZThkODUyOTE=","usersex":"0","useremail":"sniper@dota.com","nickname":"holy maria","birthday":"1989-09-09","portrait":"20150909/55efa0ec0ec6a.jpg","signature":null}
*/
类似第三方开源库
Universal-Image-Loader https://github.com/nostra13/Android-Universal-Image-Loader
1.多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
2.支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
3.支持图片的内存缓存,文件系统缓存或者SD卡缓存
4.支持图片下载过程的监听
5. 根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
6. 较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
7.提供在较慢的网络下对图片进行加载
fresco https://github.com/facebook/fresco
picasso https://github.com/square/picasso