xUtils简介

  • xUtils 包含了很多实用的android工具。
  • xUtils 源于Afinal框架,对Afinal进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持,拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响...
  • xUitls最低兼容android 2.2 (api level 8)

目前xUtils主要有四大模块:

  • DbUtils模块:
  • android中的orm框架,一行代码就可以进行增删改查;
  • 支持事务,默认关闭;
  • 可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);
  • 支持绑定外键,保存实体时外键关联实体自动保存或更新;
  • 自动加载外键关联实体,支持延时加载;
  • 支持链式表达查询,更直观的查询语义,参考下面的介绍或sample中的例子。
  • ViewUtils模块:
  • android中的ioc框架,完全注解方式就可以进行UI绑定和事件绑定;
  • 新的事件绑定方式,使用混淆工具混淆后仍可正常工作;
  • 目前支持常用的11种事件绑定,参见ViewCommonEventListener类和包com.lidroid.xutils.view.annotation.event。
  • HttpUtils模块:
  • 支持同步,异步方式的请求;
  • 支持大文件上传,上传大文件不会oom;
  • 支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD请求;
  • 下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件;
  • 返回文本内容的GET请求支持缓存,可设置默认过期时间和针对当前请求的过期时间。
  • BitmapUtils模块:
  • 加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象;
  • 支持加载网络图片和本地图片;
  • 内存管理使用lru算法,更好的管理bitmap内存;
  • 可配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等...

使用xUtils快速开发框架需要有以下权限:


<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />



一、ViewUtils  

android中得ioc(控制反转)框架,可以完全使用注解的方式来完成UI的绑定和事件绑定。简单的说,ViewUtils的功能就是做这个的,但是可以说,就这么个功能确是能极大的简化我们的代码。下面我们看下具体的代码,顺便对比下注解的方式绑定ID和findViewById之间的差别。


注解的方式绑定ID:


@ViewInject(R.id.btn)  
    private Button btn;  
    @ViewInject(R.id.img)  
    private ImageView img;   
    @ViewInject(R.id.list)  
    private ListView list;    
   @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_second);  
        ViewUtils.inject(this);}



注意:在使用注解绑定控件的时候,一定记得在onCreate中调用ViewUtils.inject(this);

findViewById获取view


@Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_second);     
        btn = (Button) findViewById(R.id.btn);  
        img = (ImageView) findViewById(R.id.img);  
        list = (ListView) findViewById(R.id.list);       
    }






下面我们再对比下Android中事件绑定的区别。



@OnClick({ R.id.btn, R.id.img })  
    public void clickMethod(View v) {  
        Toast.makeText(SecondActivity.this, "you clicked button!",  
                Toast.LENGTH_SHORT).show();  
    }  
  
    @OnItemClick(R.id.list)  
    public void itemClick(AdapterView<?> parent, View view, int position,long id) {  
        Toast.makeText(SecondActivity.this, "position--->" + position,  
                Toast.LENGTH_SHORT).show();  
    }



btn.setOnClickListener(this);  
        list.setOnItemClickListener(new OnItemClickListener() {  
            @Override  
            public void onItemClick(AdapterView<?> parent, View view,  
                    int position, long id) {  
                Toast.makeText(SecondActivity.this, "position--->" + position,  
                        Toast.LENGTH_SHORT).show();  
            }  
        });<pre name="code" class="java"><span > </span>@Override  
    public void onClick(View v) {  
        switch (v.getId()) {  
        case R.id.btn:  
            Toast.makeText(SecondActivity.this, "you clicked button!",  
                    Toast.LENGTH_SHORT).show();  
            break;  
        default:  
            break;  
        }  
    }


原本绑定Button的监听事件要么用丑陋的内部类,要么Activity实现OnClickListener,在复写的onClick方法中去根据id。而xUtils只要通过简单的一句注解就能实现监听事件的功能,而且可以实现多个控件共用一个监听方法。同时xUtils提供onClick、onItemClick、onLongClick等15种事件监听注解。

注意:在使用注解监听事件的时候,监听方法名是自定义的,但是一定要保证方法的访问修饰符为public,同时方法的参数要与Android原来的监听方法参数一致,不仅参数类型,而且要保证参数的顺序。



二、BitmapUtils 


 加载网络或本地bitmap的时候无需担心再遇到OOM的现象,管理bitmap的内存采用了LRU算法,同时也能避免列表滑动过程中发生图片错位等得现象。加载网络图片时,还可以配置运行线程的数量,缓存路径等。。。通过BitmapUtils的各种构造器,可以很方便的创建出本地缓存路径和缓存的大小,以及内存缓存的大小。



BitmapUtils utils = new BitmapUtils(this);  
    BitmapDisplayConfig config = new BitmapDisplayConfig(this);  
    config.setLoadingDrawable(getResources().getDrawable(R.drawable.loading));  
    config.setLoadFailedDrawable(getResources().getDrawable(R.drawable.failed));  
    config.setImageLoadCallBack(new ImageLoadCallBack() {  
        @Override  
        public void loadFailed(ImageView imageView, Drawable drawable) {  
        }  
        @Override  
        public void loadCompleted(ImageView imageView, Drawable drawable,  
                BitmapDisplayConfig config) {  
        }  
    });  
    config.setBitmapMaxWidth(480);  
    config.setBitmapMaxHeight(720);  
      utils.display(img, "http://img1.gtimg.com/news/pics/hv1/63/26/1451/94357968.jpg");  
    utils.display(img, "http://img1.gtimg.com/news/pics/hv1/63/26/1451/94357968.jpg", config);



BitmapUtils在用来加载网络图片时,可以配置加载图片尺寸的大小,加载成功和失败的回调以及加载过程中图片的配置。同时也可以选择不配置。




//bitmapUtils.display(testImageView, "/sdcard/test.jpg"); //支持加载本地图片  
  
// 使用ListView等容器展示图片时可通过PauseOnScrollListener控制滑动和快速滑动过程中时候暂停加载图片  
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true));  
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true), customListener);



三、HttpUtils 




ttpUtils是解决日常工作过程中繁杂的上传下载文件以及各种Get和post请求的必备工具类,通过这个类,开源非常方便关注接口的业务,不必再再写那么冗长的代码。下面全文都围绕着四个中心点去依次展开,分别是:HttpGet请求,HttpPost请求,下载文件和上传文件。



HttpGet请求。相信从事Android网络应用的开发的同学对这个一定不会陌生,长期的开发会让大家积累下一个可以复用的工具类。而xUtils就是帮助了我们把那些工具类给抽象整合成一个更具扩展性的帮助类。比如HtttpGet请求,这里只简要介绍下关键的应用方法,具体的细节还请大家自己去下载xUtils的源码去研究研究了,我们介绍的足够应用到我们的应用开发中去了。通常的HttpGet请求会把一系列的请求参数挂在请求地址的后面,拖出一节长长的尾巴,十分的惹人厌,这里可以通过像HttpPost请求的参数那样组成一个类似BasicNameValuePair的对象直接封装到请求方法中去,省去拼接url的麻烦,同时也可以设置超时时间。另外请求的方法中提供了一个回调类,这个类中有处理不同请求结果的回调方法,比如说请求过程中的回调,请求成功的回调以及请求出现错误时的回调。下面直接上代码看下。



RequestParams params = new RequestParams();  
     params.addQueryStringParameter("method", "info");  
     params.addQueryStringParameter("access_token",  
             "3.1042851f652496c9362b1cd77d4f849b.2592000.1377530363.3590808424-248414");  
  
     HttpUtils http = new HttpUtils();  
     http.configCurrentHttpGetCacheExpiry(1000 * 10);  
     http.send(HttpRequest.HttpMethod.GET,  
             "https://pcs.baidu.com/rest/2.0/pcs/quota",  
             params,  
             new RequestCallBack<String>() {  
  
                 @Override  
                 public void onStart() {  
                     resultText.setText("conn...");  
                 }  
  
                 @Override  
                 public void onLoading(long total, long current) {  
                     resultText.setText(current + "/" + total);  
                 }  
  
                 @Override  
                 public void onSuccess(String result) {  
                     resultText.setText("response:" + result);  
                 }  
  
  
                 @Override  
                 public void onFailure(HttpException error, String msg) {  
                     resultText.setText(msg);  
                 }  
             });



HttpPost请求。

为了统一请求的风格,HttpPost请求的方式和HttpGet的几乎可以说是一模一样,一样提供了各种对应不同结果的回调方法,大家自己看下面的代码就晓得了,真是一目了然。



RequestParams params = new RequestParams();  
       params.addQueryStringParameter("method", "mkdir");  
       params.addQueryStringParameter("access_token", "3.1042851f652496c9362b1cd77d4f849b.2592000.1377530363.3590808424-248414");  
       params.addBodyParameter("path", "/apps/测试应用/test文件夹");  
  
       HttpUtils http = new HttpUtils();  
       http.send(HttpRequest.HttpMethod.POST,  
               "https://pcs.baidu.com/rest/2.0/pcs/file",  
               params,  
               new RequestCallBack<String>() {  
  
                   @Override  
                   public void onStart() {  
                       resultText.setText("conn...");  
                   }  
  
                   @Override  
                   public void onLoading(long total, long current) {  
                       resultText.setText(current + "/" + total);  
                   }  
  
                   @Override  
                   public void onSuccess(String result) {  
                       resultText.setText("upload response:" + result);  
                   }  
  
  
                   @Override  
                   public void onFailure(HttpException error, String msg) {  
                       resultText.setText(msg);  
                   }  
               });



下面为大家介绍一个非常非常实用的功能,就是通过Http协议去下载文件,再也不必为Android中下载文件而写下一大坨一大坨的代码,如此长的代码调试起来真是能气死人。还记得以前做过一个项目,有个需求就是能下载视频的,而且还要能支持断点下载,只写那么一个下载工具类就写了一两天,再加上调试,真心把人都给逼疯了。要是xUtils早点在那个时候面世,想那时做那个需求也不必那么通过。HttpUtils为开发者提供了非常方便的下载api,可以通过简单的几个参数来实现下载,甚至断点下载的功能。上代码。




HttpHandler  handler = http.download(  
                downloadAddrEdit.getText().toString(),  
                "/sdcard/fileexplorer.apk",  
                true, // 如果目标文件存在,接着未完成的部分继续下载。  
                true, // 如果从请求返回信息中获取到文件名,下载完成后自动重命名。  
                new RequestCallBack<File>() {   
  
                    @Override  
                    public void onStart() {  
                        resultText.setText("conn...");  
                    }  
  
                    @Override  
                    public void onLoading(long total, long current) {  
                        resultText.setText(current + "/" + total);  
                    }  
  
                    @Override  
                    public void onSuccess(File result) {  
                        resultText.setText("downloaded:" + result.getPath());  
                    }  
  
                    @Override  
                    public void onFailure(HttpException error, String msg) {  
                        resultText.setText(error.getExceptionCode() + ":" + msg);  
                    }  
                });



注意:下载过程中如果需要暂停下载,也只需简单的一行代码来实现:mHandler.stop(),如果设置断点下载的话,下次会重新开始的话,会自动从上次下载的断点处继续下载。




最后介绍的功能就是上传文件了,这个也是在项目中也是非常常见的。比如用户上传头像,再比如网盘应用需要把本地文件上传到云端等等。同时HttpUtils也同时为开发者提供了上传过程中和上传结果的各个回调接口。大家在使用HttpUtils上传文件的时候,只要仿照下面的代码去码代码就快可以基本满足业务的需要了。



RequestParams params = new RequestParams();  
        params.addQueryStringParameter("method", "upload");  
        params.addQueryStringParameter("path", "/apps/测试应用/test.zip");  
        // 请在百度的开放access_tokenapi测试页面找到自己的access_token  
        params.addQueryStringParameter("access_token", "3.1042851f652496c9362b1cd77d4f849b.2592000.1377530363.3590808424-248414");  
        params.addBodyParameter("file", new File("/sdcard/test.zip"));  
  
        HttpUtils http = new HttpUtils();  
        http.send(HttpRequest.HttpMethod.POST,  
                "https://pcs.baidu.com/rest/2.0/pcs/file",  
                params,  
                new RequestCallBack<String>() {  
  
                    @Override  
                    public void onStart() {  
                        resultText.setText("conn...");  
                    }  
  
                    @Override  
                    public void onLoading(long total, long current) {  
                        resultText.setText(current + "/" + total);  
                    }  
  
                    @Override  
                    public void onSuccess(String result) {  
                        resultText.setText("upload response:" + result);  
                    }  
  
  
                    @Override  
                    public void onFailure(HttpException error, String msg) {  
                        resultText.setText(msg);  
                    }  
                });



四、DbUtils



操纵数据库的工具类,无论多牛X,总离不开最根本的CRUD,即创建,查询,更新和删除。下面从这四个角度依次介绍xUtils是如何简便持久化数据的。大家都知道,在Android里面如果要存储一个对象,我们需要创建一个SQLiteOpenHelper,然后还得创建一张对应对象各个属性的表,还得继续把我们的对象转换成ContentValues,进而去存储。真心是麻烦的不能再麻烦了,我们现在介绍的DbUtils就能让你轻松解脱麻绳一样的代码。DbUtils在进行save操作的时候,会根据java反射反射出对象的各个字段,然后去查询数据库中是否存在这个对象类型对应的表,如果表已经存在,直接进行插入操作;如果不存在,就先动态的创建的一张对应我们对象的表,再进行插入处理。直接上代码,大家看。



@OnClick(R.id.insert)  
    public void insert(View v) {  
        Student stu = null;  
        for (int i = 0; i < 20; i++) {  
            stu = new Student();  
            stu.setAge(10 + i);  
            stu.setName("jack" + i);  
            mList.add(stu);  
            try {  
                dbUtils.save(stu);  
            } catch (DbException e) {  
                e.printStackTrace();  
            }  
        }  
    }



注意:并不是所有的实体对象都快可以通过这种方式去存储,一定要保证对象的类型中有int类型的id或者_id的属性,这就对应数据库表中的主键字段。如果类型中没有id字段,可以通过@Id注解去指定一个int类型的字段作为主键。如果表中的又字段不想被存储在数据库中,也可以通过@Transient去实现忽略。如果直接存储一个对象的列表,这样也是被允许的,达到批量存储的目的。


DbUtils可以帮助对SQL语句不是很熟悉的同学快速的实现查询,而不用去写sql查询语句,而且可以对查询结果进行排序和分页,使用简单,功能强大。大家可以看下,下面的几行代码就能实现复杂的查询功能

dbUtils.findAll(Selector.from(Student.class).where("_id", "<", 10).and("age", ">", 10).orderBy("_id").limit(pageSize).offset(pageSize * pageIndex));


同样的,也可以对数据库中得数据进行便捷的更新。下面演示的是更新Student对应的表中的第一条记录的age这个字段。这个比较简单,就直接上代码看吧。



@OnClick(R.id.update)  
    public void update(View v){  
        try {  
            List<Student> stus = dbUtils.findAll(Selector.from(Student.class));  
            Student stu = stus.get(0);  
            stu.setAge(20);  
            dbUtils.update(stu);  
        } catch (DbException e) {  
            e.printStackTrace();  
        }  
    }


最后一个就是数据的删除。一个实体对象,一组实体对象,根据条件删除,删除表,删除整个数据库,这些操作都可以通过一句简单的代码来实现,看了代码就明白了。



@OnClick(R.id.delete)  
    public void delete(View v){  
        try {  
            List<Student> stus = dbUtils.findAll(Selector.from(Student.class));  
            dbUtils.delete(stus.get(0));  
            dbUtils.deleteAll(stus);  
            dbUtils.deleteById(Student.class, WhereBuilder.b("age", "==", 20));  
            dbUtils.dropTable(Student.class);  
            dbUtils.dropDb();  
        } catch (DbException e) {  
            e.printStackTrace();  
        }  
    }