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实现图片的加载
- ImageRequest的用法
前面我们已经学习过了StringRequest和JsonRequest的用法,并且总结出了它们的用法都是非常类似的,基本就是进行以下三步操作即可:
创建一个RequestQueue对象。
创建一个Request对象。
将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, 没有缓存数据); }}
- ImageLoader的用法
如果你觉得ImageRequest已经非常好用了,那我只能说你太容易满足了 ^_^。实际上,Volley在请求网络图片方面可以做到的还远远不止这些,而ImageLoader就是一个很好的例子。ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。
由于ImageLoader已经不是继承自Request的了,所以它的用法也和我们之前学到的内容有所不同,总结起来大致可以分为以下四步:
创建一个RequestQueue对象。
创建一个ImageLoader对象。
获取一个ImageListener对象。
调用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); }}
- Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils
- Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils
- DbUtils和HttpUtils
- android通过注解实现findViewById 和 setOnClickListener
- setOnClickListener(this)是什么意思?
- 手写IOC注解,解决findViewById和点击事件
- 通过注释省略findviewbyid
- xUtils类库(BitmapUtils、ViewUtils、DbUtils、HttpUtils)使用介绍
- jquery得到点击事件的this对象
- andriod item内checked的setOnClickListener事件和setOnItemClickListener事件冲突解决办法
- Activity的findViewById()和View的findViewById()
- 用注解来省略findViewById
- Android Studio 中 View 的 setOnClickListener 添加方法(不能用this)
- this 的体验在类内可省略
- clearButton.setOnClickListener(this);
- 很多点击事件,通过方法减少使用findViewbyid
- listview条目点击事件无效(或者需要同时监听条目点击事件和子控件的点击事件)
- 关于View的setOnTouchListener和setOnClickListener冲突
- Eclipse Maven插件的安装
- 软件运行在64位win7没有问题,但是在32位win7运行出现BEX错误
- 素数表生成
- 启动 Eclipse 弹出“Failed to load the JNI shared library jvm.dll”错误的解决方法!
- iOS学习笔记:instancetype关联返回类型
- Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils
- 测试分页接口
- ViewPager与SwipeRefreshLayout冲突问题
- Android之Json转换利器Gson之实例一-简单对象转化和带泛型的List转化
- BZOJ 3684 大朋友与多叉树 多项式求幂/求exp+拉格朗日反演
- HDU 5441 Travel(求各个集合里的秩能组合多少对,只能在一个集合里组合)
- 关于json一片号的文章,转载来收藏一下
- web_custom_request 例子
- 如果浏览器不支持 cookie 该怎么办?