Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils

来源:互联网 发布:短信群发软件下载 编辑:程序博客网 时间:2024/05/24 04:27

Volley

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的表现就会非常糟糕。

Volley原理

Volley的原理:在连接网络时,Volley会先在缓存中找,如果缓存中有这样的响应,就直接返回给UI,如果没有就去线程缓存池中找线程,在线程缓存池中的线程个数是有限的,如果没有线程,就新建立一个线程。如果有就等待这个线程完成任务,然后获得返回值信息。而不是新建一个线程。如下图所示:
这里写图片描述

Volley的导入:

android Studio在项目中右键——>open Modul Setting——>Depending——>‘+’——>files library 搜索Volley下载就可以了。

StringRequest的用法

1)建立一个相应队列
2)建立一个响应,第一个参数为;响应方法:POST,GET。第二个参数为Url,第三个为:响应成功时执行,第四个为失败时执行
3)将响应加入响应队列
注意:不要忘记导包:在项目中右键——>open Modul Setting——>Depending——>+——files library 搜索Volley下载就可以了。
4)如果是POST方法则建立一个StringRequest的匿名内部类,复写getParams()方法,在这个方法中建立一个map容器,将数据加载到map中,最后返回map就可以了。

代码如下:
GET方法:

RequestQueue queue = Volley.newRequestQueue(this);//建立一个相应队列                //建立一个响应,第一个参数为;响应方法:POST,GET。第二个参数为Url,第三个为:响应成功时执行,第四个为失败时执行                 StringRequest request = new StringRequest(Request.Method.GET, "http://360.com", new Response.Listener<String>() {                    @Override                    public void onResponse(String response) {                            textView_Volley.setText(response);                    }                }, new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        textView_Volley.setText("错误");                    }                });                queue.add(request);//将响应加入响应队列

POST方法:

  RequestQueue queue = Volley.newRequestQueue(this);//建立一个相应队列                //建立一个响应,第一个参数为;响应方法:POST,GET。第二个参数为Url,第三个为:响应成功时执行,第四个为失败时执行                 StringRequest request = new StringRequest(Request.Method.POST, "http://192.168.0.43:8080/www/MyserverTest", new Response.Listener<String>() {                    @Override                    public void onResponse(String response) {                            textView_Volley.setText(response);                    }                }, new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        textView_Volley.setText("错误");                    }                }){                     @Override                     protected Map<String, String> getParams() throws AuthFailureError {                        Map<String,String> map = new HashMap<>();                         map.put("name","xiaoming");                         map.put("password","123");                         return map;                     }                 };                queue.add(request);//将响应加入响应队列

单例设计模式

Volley可以避免建立许多的线程去请求网络,但它不能避免建立多个RequestQueue ,所以我们一般是用单例模式去创建RequestQueue 的实例。代码如下:

public class Mysinger {        private static Mysinger mysinger;        private static RequestQueue requestQueue;        public static RequestQueue getRequestQueue() {            return requestQueue;        }        private  Mysinger (Context context){            requestQueue = Volley.newRequestQueue(context);        }        public static synchronized  Mysinger getInstance( Context context){            if(mysinger==null){                mysinger= new Mysinger(context);            }            return mysinger;        }}

Volley实现图片的加载

  1. ImageRequest的用法

前面我们已经学习过了StringRequest和JsonRequest的用法,并且总结出了它们的用法都是非常类似的,基本就是进行以下三步操作即可:

  1. 创建一个RequestQueue对象。

  2. 创建一个Request对象。

  3. 将Request对象添加到RequestQueue里面。

其中,StringRequest和JsonRequest都是继承自Request的,所以它们的用法才会如此类似。那么不用多说,今天我们要学习的ImageRequest,相信你从名字上就已经猜出来了,它也是继承自Request的,因此它的用法也是基本相同的,首先需要获取到一个RequestQueue对象,可以调用如下方法获取到:

RequestQueue mQueue = Volley.newRequestQueue(context);

接下来自然要去new出一个ImageRequest对象了,代码如下所示:

    ImageRequest imageRequest = new ImageRequest(              "http://developer.android.com/images/home/aw_dac.png",              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);                  }              });  

可以看到,ImageRequest的构造函数接收六个参数,第一个参数就是图片的URL地址,这个没什么需要解释的。第二个参数是图片请求成功的回调,这里我们把返回的Bitmap参数设置到ImageView中。第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不会进行压缩。第五个参数用于指定图片的颜色属性,Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而RGB_565则表示每个图片像素占据2个字节大小。第六个参数是图片请求失败的回调,这里我们当请求失败时在ImageView中显示一张默认图片。

最后将这个ImageRequest对象添加到RequestQueue里就可以了,如下所示:

mQueue.add(imageRequest);

这里写图片描述

Volley获取缓存

从架构上我们可以看到,volley有设置缓存机制,当找不到数据缓存或数据缓存过期时,才会联网获取新的数据。Volley 本身有缓存机制,不仅仅默认缓存图片,也有缓存Json数据。通过手机文件管理软件,我们发现Volley缓存地址:/data/data/软件包/cache/volley 目录下。

那么,在联网获取了数据缓存后,如何获取到Volley缓存中的数据呢?在百度上找了一整天的资料都没有说明如何获取到最新的数据。最后还是再stack overflow中找到了相关的资料。

RequestQueue类中有一个子函数getCache()可以返回Cache实例,通过调用改实例中的get(url)函数可以查看手机磁盘中是否保存有缓存数据,其成员变量data保存着缓存的数据内容。即:queue.getCache().get(url).data

所以,我们可以通过以下语句,来选择获取缓存数据或者向服务器获取最新数据。

if(queue.getCache().get(url)!=null){  //response exists  String cachedResponse = new String(queue.getCache().get(url).data);}else{  //no response  queue.add(stringRequest);}

其实这样做还是有缺陷的,那就是如果服务器更新了数据的话,则我们客户端没办法获取最新数据,而是从缓存中调取缓存数据。

为此,我一个比较笨的方法是:判断网络是否可用,如果可用则更新数据,当网络不可用时,采用缓存数据。

Context context = getActivity().getApplicationContext();if(!isNetworkAvailable(context)){    getFromDiskCache(url);               //如果没网,则调取缓存数据}else{//有网则从网上更新数据                 //……(省略)}

其中isNetworkAvailable()函数用于判断网络是否可用:

public static boolean isNetworkAvailable(Context context) {       try {        ConnectivityManager manger = (ConnectivityManager) context                .getSystemService(Context.CONNECTIVITY_SERVICE);         NetworkInfo info = manger.getActiveNetworkInfo();        //return (info!=null && info.isConnected());        if(info != null){            return info.isConnected();        }else{            return false;        }    } catch (Exception e) {        return false;    }}

getFromDiskCache()函数用于获取缓存数据(以JSONArray为例):

private void getFromDiskCache(String url) {    if(mQueue.getCache().get(url)!=null){        try {            String str = new String((mQueue.getCache().get(url).data);            JSONArray response = new JSONArray(str);            //……(省略操作)        } catch (JSONException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }else{        Log.d(TAG, 没有缓存数据);      }}
  1. ImageLoader的用法

如果你觉得ImageRequest已经非常好用了,那我只能说你太容易满足了 ^_^。实际上,Volley在请求网络图片方面可以做到的还远远不止这些,而ImageLoader就是一个很好的例子。ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。

由于ImageLoader已经不是继承自Request的了,所以它的用法也和我们之前学到的内容有所不同,总结起来大致可以分为以下四步:

  1. 创建一个RequestQueue对象。

  2. 创建一个ImageLoader对象。

  3. 获取一个ImageListener对象。

  4. 调用ImageLoader的get()方法加载网络上的图片。

下面我们就来按照这个步骤,学习一下ImageLoader的用法吧。首先第一步的创建RequestQueue对象我们已经写过很多遍了,相信已经不用再重复介绍了,那么就从第二步开始学习吧,新建一个ImageLoader对象,代码如下所示:

    ImageLoader imageLoader = new ImageLoader(mQueue, new ImageCache() {          @Override         public void putBitmap(String url, Bitmap bitmap) {          }          @Override         public Bitmap getBitmap(String url) {              return null;          }      });  

可以看到,ImageLoader的构造函数接收两个参数,第一个参数就是RequestQueue对象,第二个参数是一个ImageCache对象,这里我们先new出一个空的ImageCache的实现即可。

接下来需要获取一个ImageListener对象,代码如下所示:

    ImageListener listener = ImageLoader.getImageListener(imageView,              R.drawable.default_image, R.drawable.failed_image);  

我们通过调用ImageLoader的getImageListener()方法能够获取到一个ImageListener对象,getImageListener()方法接收三个参数,第一个参数指定用于显示图片的ImageView控件,第二个参数指定加载图片的过程中显示的图片,第三个参数指定加载图片失败的情况下显示的图片。

最后,调用ImageLoader的get()方法来加载图片,代码如下所示:

imageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", listener);

get()方法接收两个参数,第一个参数就是图片的URL地址,第二个参数则是刚刚获取到的ImageListener对象。当然,如果你想对图片的大小进行限制,也可以使用get()方法的重载,指定图片允许的最大宽度和高度,如下所示:

imageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg",                listener, 200, 200);

现在运行一下程序并开始加载图片,你将看到ImageView中会先显示一张默认的图片,等到网络上的图片加载完成后,ImageView则会自动显示该图,效果如下图所示。

这里写图片描述

HttpUtils

HttpUtils也是连接网络的一种框架,也是分为POST方法和GET方法。
注意要导包,在android Studio在项目中右键——>open Modul Setting——>Depending——>‘+’——>files library 搜索xutils下载就可以了。有时还不起作用,运行一下就可以了。
代码如下:

 HttpUtils client = new HttpUtils();                client.send(HttpRequest.HttpMethod.GET, "http://www.baidu.com", new RequestCallBack<String>() {                    @Override                    public void onSuccess(ResponseInfo<String> responseInfo) {                        utils_textView.setText(responseInfo.result);                    }                    @Override                    public void onFailure(HttpException e, String s) {                        utils_textView.setText("错误");                    }                });

POST方法:

 HttpUtils client = new HttpUtils();                RequestParams params = new RequestParams();                params.addBodyParameter("name", "liujiaorui");                params.addBodyParameter("password", "12qa");                client.send(HttpRequest.HttpMethod.POST, "http://192.168.0.198:8080/MyAndroidServlet/MyServlet", params, new RequestCallBack<String>() {                    @Override                    public void onSuccess(ResponseInfo<String> responseInfo) {                        mTextViewcontent.setText(responseInfo.result);                    }                    @Override                    public void onFailure(HttpException e, String s) {                        mTextViewcontent.setText("网络连接错误");                    }                });

省略findViewById()和点击事件的.setOnClickListener(this);

当我们导入xutils包后,可以利用注解机制省略很多代码,例如每个控件的findViewById()和点击事件的.setOnClickListener(this);
1)在Activity中给声明的控件加注解,例如:

  @ViewInject(R.id.util_button)    private Button utils_button;    @ViewInject(R.id.textView_utils)    private TextView utils_textView;

这里@ViewInject(R.id.util_button)的util_button为XML中的控件的id。
2)如果想给控件加点击事件,则可以不用加.setOnClickListener(this);
而是在onCreat()加上

   ViewUtils.inject(this);

然后再 ViewUtils.inject(this);的上面加上要加控件点击事件的数组就可以了:

 @OnClick({R.id.util_button,R.id.dd})

这样就省略了很多的方法。

DbUtils

DbUtils主要用于对数据库的查询;
可以通过DbUtils实现轻松的数据库查询,
1)新建一个类,例如User。在类的上面@Table(name = “user”)。注意:user为要访问的表格的名称。
2)新建变量,这里的变量名与表格的字段名保持一致。必须在id字段的上面 @Column(column = “id”)这里的id也与表格的名字对应。
3)在Activity的点击事件的查询事件中。输入一下代码:

  //建立DbUtils对象,MY_BASE.db为数据库的名字                DbUtils dbUtils= DbUtils.create(this,"MY_BASE.db");                try {                    //用DbUtils调用各种方法进行查询,并将查询的结果放到装User的List中。                 List<User>  users=dbUtils.findAll(com.lidroid.xutils.db.sqlite.Selector.from(User.class));                    //对查询的结果进行打印                    for(User user:users){                        Log.d("aaaaaaaaa","用户名"+user.getName()+"密码"+user.getPassword());                    }                } catch (DbException e) {                    e.printStackTrace();                }

这要比以前简单的多。

这是在网上找的代码,参考一下:

private void testDb() {    Parent parent = new Parent();    parent.name = "测试";    parent.isVIP = false;    parent.setAdmin(true);    parent.setEmail("wyouflf@gmail.com");    /*Parent parent2 = new Parent();    parent2.name = "测试2";    parent2.isVIP = false;*/    Child child = new Child();    child.name = "child name";    child.parent = parent;    try {        DbUtils db = DbUtils.create(this, true);        try {            Parent test = db.findFirst(parent);//通过entity的属性查找            LogUtils.d("wyouflf :" + test);        } catch (Exception e) {            LogUtils.e(e.getMessage(), e);        }        parent.setTime(new Date());        parent.setTime2(new java.sql.Date(new Date().getTime()));        db.saveBindingId(child);//保存对象关联数据库生成的id        List<Child> children = db.findAll(Selector.from(Child.class));        LogUtils.d("wyouflf size:" + children.size());        if (children.size() > 0) {            LogUtils.d("wyouflf child:" + children.get(children.size() - 1).parent);        }        List<Parent> list = db.findAll(Selector.from(Parent.class).where(WhereBuilder.b("id", "<", 54).append("name","=","测试")).orderBy("id").limit(10));        LogUtils.d("wyouflf size:" + list.size());        if (list.size() > 0) {            LogUtils.d("wyouflf parent:" + list.get(list.size() - 1).toString());        }        //parent.name = "hahaha123";        //db.update(parent);        Parent entity = db.findById(Parent.class, parent.getId());        LogUtils.d("wyouflf parent:" + entity.toString());        List<DbModel> dbModels = db.findDbModelAll(Selector.from(Parent.class).groupBy("name").select("name", "count(name)"));        LogUtils.d("wyouflf:" + dbModels.size());    } catch (DbException e) {        LogUtils.e(e.getMessage(), e);    }}
0 0
原创粉丝点击