xUtils使用详解(一)

来源:互联网 发布:计算机通信与网络 编辑:程序博客网 时间:2024/05/16 15:41

    一直都听闻有个xUtils,但是没有使用过。最近有一个小项目,需要快速开发,工期较短,所以,就想到了xUtils。

    目前xUtils已经发布到xUtils3,所以,我们就按照xUtils3的规范来开发。xUtils系列框架提供的功能主要有四大模块,ViewUtils模块、BitmapUtils模块、DbUtils模块、HttpUtils模块。下面,我们就从这4方面介绍具体xUtils3的使用。

一、使用前配置。

使用Android Studio开发时,我们需要在build.gradle文件中添加依赖:

compile 'org.xutils:xutils:3.5.0'
(如果还是使用Eclipse,需要自行下载jar包导入至项目中即可。本篇文章是以Android Studio开发)

并且我们还需要在AndroidManifest.xml文件中添加网络权限,具体权限如下,

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

二、使用。

创建Application,在它的onCreate()方法中添加初始化代码,具体代码如下,

public class MyApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        x.Ext.init(this);        x.Ext.setDebug(false); // 是否输出debug日志,开启debug会影响性能    }}

记得要在AndroidManifest.xml文件中添加我们自定义的MyApplication,代码如下,

 <application            android:name=".MyApplication"            android:allowBackup="true"            android:icon="@mipmap/ic_launcher"            android:label="@string/app_name"            android:supportsRtl="true"            android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter>        </activity>    </application>

PS:我们通过源码看看x类的描述,

      /**      * Created by wyouflf on 15/6/10.      * 任务控制中心, http, image, db, view注入等接口的入口.      * 需要在在application的onCreate中初始化: x.Ext.init(this);      */      public final class x 

      x.Ext.init(this);      public static void init(Application app) {            TaskControllerImpl.registerInstance();//实例化异步任务的管理类            if (Ext.app == null) {                Ext.app = app;            }        }

下面分别介绍这四大模块的使用。

三.ViewUtils模块。

(1).android中的ioc框架,完全注解方式就可以进行UI,资源和事件绑定;(2).新的事件绑定方式,使用混淆工具混淆后仍可正常工作;(3).目前支持常用的20种事件绑定,参见ViewCommonEventListener类和包com.lidroid.xutils.view.annotation.event。

使用注解可以简化许多重复的工作。记得要使用注解功能,需要先初始化注解模块!

1.在Activity中使用注解

在Activity的onCreate()中需要初始化注解框架,具体写法如下,

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        x.view().inject(this);//初始化注解模块    }

加载布局,

@ContentView(R.layout.activity_main)
绑定控件,
    @ViewInject(R.id.tv_msg)    TextView mTvMsg;    @ViewInject(R.id.btn_start)    Button mStartBtn;
事件监听,
    @Event(value=R.id.btn_start,type = View.OnClickListener.class)    private void startLoading(View v){        Toast.makeText(this, "startLoading", Toast.LENGTH_SHORT).show();    }
使用@Event事件注解事,需要注意以下几点,

 * 1. 方法必须私有限定, * 2. 方法参数形式必须和type对应的Listener接口一致. * 3. 注解参数value支持数组: value={id1, id2, id3} * 4. 其它参数说明见{@link org.xutils.event.annotation.Event}类的说明. * 5. type,可选参数, 默认是View.OnClickListener.class,需要根据实际情况来确定具体的值,例如长按事件,type = View.OnLongClickListener.class.
2.在Fragment中使用注解

在Fragment中初始化注解框架,与Activity稍有不同,

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        return  x.view().inject(this,inflater,container);    }
在Fragment中使用注解和Activity中是一样的,此处就不在细说。
下面给出Activity全部代码,
@ContentView(R.layout.activity_main)public class MainActivity extends AppCompatActivity {    @ViewInject(R.id.tv_msg)    TextView mTvMsg;    @ViewInject(R.id.btn_start)    Button mStartBtn;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        x.view().inject(this);    }    @Event(value=R.id.btn_start,type = View.OnLongClickListener.class)    private void startLoading(View v){        Toast.makeText(this, "startLoading", Toast.LENGTH_SHORT).show();    }}
有关注解使用,就到这儿!如果还想了解更多,可以去xUtils的github上看它们的sample。

四.BitmapUtils模块。

(1).加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象;(2).支持加载网络图片和本地图片;(3).内存管理使用lru算法,更好的管理bitmap内存;(4).可配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等...
图片加载,xUtils提供多种加载图片的方式,本地加载、缓存加载、网络加载,支持加载gif等,如下所示,

x.image().bind(imageView, url, imageOptions);// assets filex.image().bind(imageView, "assets://test.gif", imageOptions);// local filex.image().bind(imageView, new File("/sdcard/test.gif").toURI().toString(), imageOptions);x.image().bind(imageView, "/sdcard/test.gif", imageOptions);x.image().bind(imageView, "file:///sdcard/test.gif", imageOptions);x.image().bind(imageView, "file:/sdcard/test.gif", imageOptions);x.image().bind(imageView, url, imageOptions, new Callback.CommonCallback<Drawable>() {...});x.image().loadDrawable(url, imageOptions, new Callback.CommonCallback<Drawable>() {...});// 用来获取缓存文件x.image().loadFile(url, imageOptions, new Callback.CommonCallback<File>() {...});
上面的方法中都有一个ImageOptions参数,我们看看这是什么鬼!ImageOptions可以设置一些属性,方便加载图片,下面是它的基本属性设置,

                .setSize(DensityUtil.dip2px(60),DensityUtil.dip2px(60))//设置图片大小
                .setRadius(DensityUtil.dip2px(5))//圆角半径
                .setCrop(true)//是否对图片进行裁剪,如果ImageView的大小不是定义为wrap_content, 不要crop.
                .setImageScaleType()//设置图片的缩放格式
                .setFadeIn(true)//设置淡入效果
                .setLoadingDrawableId(R.mipmap.ic_launcher)//设置加载过程中显示的图片
                .setFailureDrawableId(R.mipmap.ic_launcher)//设置加载失败显示的图片
                .setUseMemCache(true)//设置使用缓存
                .setCircular(true)//设置图片显示为圆形
                .setSquare(true);//设置图片显示为正方形
                .setIgnoreGif(true)//设置支持gif
                .setAnimation()//设置动画

下面展示使用用例,

   ...    @ViewInject(R.id.iv_pic)    ImageView mIvPic;    ImageOptions mImageOptions;    private String mPicPath="http://pic33.nipic.com/20130916/3420027_192919547000_2.jpg";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        x.view().inject(this);        mImageOptions=new ImageOptions.Builder()                .setSize(DensityUtil.dip2px(100),DensityUtil.dip2px(100))//设置图片大小                .setRadius(DensityUtil.dip2px(5))//圆角半径                .setCrop(true)//是否对图片进行裁剪,如果ImageView的大小不是定义为wrap_content, 不要crop                .setFadeIn(true)//设置淡入效果                .setLoadingDrawableId(R.mipmap.ic_launcher)//设置加载过程中显示的图片                .setFailureDrawableId(R.mipmap.ic_launcher)//设置加载失败显示的图片                .setUseMemCache(true)//设置使用缓存                .setCircular(true)//设置图片显示为圆形                .setIgnoreGif(true)//设置支持gif                .build();    }    @Event(value=R.id.btn_start,type = View.OnClickListener.class)    private void startLoading(View v){        x.image().bind(mIvPic,mPicPath,mImageOptions);    }...
运行效果图,如下所示,

PS:Callback.CommonCallback<Drawable>  回调方法(这个地方使用它,更加灵活、方便地加载图片)

    new Callback.CommonCallback<Drawable>() {            @Override            public void onSuccess(Drawable result) {//获取成功            }            @Override            public void onError(Throwable ex, boolean isOnCallback) {//获取失败            }            @Override            public void onCancelled(CancelledException cex) {//取消操作            }            @Override            public void onFinished() {//完成操作            }        }
图片加载其他方法的使用,请详看xUtils的github上的sample以及源码。

五.DbUtils模块。

(1).android中的orm框架,一行代码就可以进行增删改查;(2).支持事务,默认关闭;(3).可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);(4).支持绑定外键,保存实体时外键关联实体自动保存或更新;(5).自动加载外键关联实体,支持延时加载;(6).支持链式表达查询,更直观的查询语义。
首先,我们需要定义数据库初始化配置数据,为了统一管理,数据库初始化配置可以放在一个单例类中或者自定义的Application中,需要添加如下代码,

...           private DbManager.DaoConfig daoConfig;           public DbManager.DaoConfig getDaoConfig() {             return daoConfig;            }...                daoConfig = new DbManager.DaoConfig()                .setDbName("utils.db")//设置数据库的名称,默认是xutils.db                .setAllowTransaction(true)//设置是否允许事务,默认true                .setDbDir(new File("/sdcard")) // 设置数据库的存放路径, 默认存储在app的私有目录(数据库默认存储在/data/data/你的应用程序/database/xxx.db)                .setDbVersion(1)//设置数据库的版本号                //设置数据库打开的监听                .setDbOpenListener(new DbManager.DbOpenListener() {                    @Override                    public void onDbOpened(DbManager db) {                        // 开启WAL, 对写入加速提升巨大                        db.getDatabase().enableWriteAheadLogging();                    }                })                //设置数据库更新的监听                .setDbUpgradeListener(new DbManager.DbUpgradeListener() {                    @Override                    public void onUpgrade(DbManager db, int oldVersion, int newVersion) {                        // TODO: ...                        // db.addColumn(...);                        // db.dropTable(...);                        // ...                        // or                        // db.dropDb();                    }                });...    

此时,数据库还未创建!只有当我们执行以下代码,

DbManager db=x.getDb(new DaoConfig());
通过源码,我们可以得知,当数据库不存在时,就会创建数据库;如果数据库已经存在,则打开数据库。
    private DbManagerImpl(DaoConfig config) {        if (config == null) {            throw new IllegalArgumentException("daoConfig may not be null");        }        this.daoConfig = config;        this.allowTransaction = config.isAllowTransaction();        this.database = openOrCreateDatabase(config);        DbOpenListener dbOpenListener = config.getDbOpenListener();        if (dbOpenListener != null) {            dbOpenListener.onDbOpened(this);        }    }

接着创建一个实体类,该实体类对应一张表,例如,

@Table(name = "tb_user")public class Users {    @Column(name = "id", isId = true)    private int id;    @Column(name = "name")    private String name;    @Column(name = "age")    private int age;    @Column(name = "mobile")    private String mobile;    public Users() {    }    public Users(String name, int age, String mobile) {        setName(name);        setAge(age);        setMobile(mobile);    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getMobile() {        return mobile;    }    public void setMobile(String mobile) {        this.mobile = mobile;    }    @Override    public String toString() {        return "Users{" +                "id=" + id +                ", name='" + name + '\'' +                ", age=" + age +                ", mobile='" + mobile + '\'' +                '}';    }}
使用注解来标注表名和列名,并且记得实体类要有无参的构造函数,以及实现get()、set()方法,否则可能会报错!

下面我们分别看看框架提供的CRUD方法。

1.新增数据。

    /**     * 保存实体类或实体类的List到数据库,     * 如果该类型的id是自动生成的, 则保存完后会给id赋值.     *     * @param entity     * @return     * @throws DbException     */    boolean saveBindingId(Object entity) throws DbException;    /**     * 保存或更新实体类或实体类的List到数据库, 根据id对应的数据是否存在.     *     * @param entity     * @throws DbException     */    void saveOrUpdate(Object entity) throws DbException;    /**     * 保存实体类或实体类的List到数据库     *     * @param entity     * @throws DbException     */    void save(Object entity) throws DbException;    /**     * 保存或更新实体类或实体类的List到数据库, 根据id和其他唯一索引判断数据是否存在.     *     * @param entity     * @throws DbException     */    void replace(Object entity) throws DbException;
例如新增数据,
 DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        Users u=new Users();        u.setMobile("12345567890");        u.setAge(9);        u.setName("zhangsan");        try {            db.save(u);//创建表,并把数据存入        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


如果想要显示表中的字段名,可以输入命令,‘.header on’,


save()方法还支持传递一个列表,例如,

        DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        Users u1=new Users();        u1.setMobile("12");        u1.setAge(12);        u1.setName("li");        Users u2 = new Users();        u2.setMobile("13");        u2.setAge(13);        u2.setName("wang");        List<Users> userList= new ArrayList<>();        userList.add(u1);        userList.add(u2);        try {            db.save(userList);        } catch (DbException e) {            e.printStackTrace();        }
运行效果图如下所示,


其他方法就不一一列举了!

2.查询操作。

查询数据

    <T> T findById(Class<T> entityType, Object idValue) throws DbException;    <T> T findFirst(Class<T> entityType) throws DbException;    <T> List<T> findAll(Class<T> entityType) throws DbException;    <T> Selector<T> selector(Class<T> entityType) throws DbException;    DbModel findDbModelFirst(SqlInfo sqlInfo) throws DbException;    List<DbModel> findDbModelAll(SqlInfo sqlInfo) throws DbException;

(1).findById(Class<T> entityType, Object idValue)

通过主键从表中查找数据

 DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            Users u=db.findById(Users.class,2);            Log.e("Users",u.toString());        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


(2).findFirst(Class<T> entityType)

返回当前表中的第一条数据

        DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            Users u=db.findFirst(Users.class);            Log.e("Users",u.toString());        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


(3).findAll(Class<T> entityType)

返回当前表中的所有数据

        DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        List<Users> list= null;        try {            list = db.findAll(Users.class);            for (int i=0;i<list.size();i++){                LogUtil.e("user"+list.get(i).toString());            }        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


(4).DbModel findDbModelFirst(SqlInfo sqlInfo)

PS:DbModel内部是HashMap,(键是列名,值是对应的数据)。

        SqlInfo参数是sql查询语句。

根据查询条件返回第一条数据,并组装为DbModel。

 DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            DbModel dbModel=db.findDbModelFirst(new SqlInfo("select * from tb_user"));            LogUtil.i("name="+dbModel.getString("name")+",age"+dbModel.getString("age"));        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


(5).List<DbModel> findDbModelAll(SqlInfo sqlInfo)

根据查询条件返回数据,并组装为DbModel列表。

      DbManager db = x.getDb(((MyApplication) getApplicationContext()).getDaoConfig());        try {            List<DbModel> dbModelAll = db.findDbModelAll(new SqlInfo("select * from tb_user"));            for (DbModel dbModel : dbModelAll) {                LogUtil.i("name=" + dbModel.getString("name") + ",age" + dbModel.getString("age"));            }        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


(6).selector(Class<T> entityType)

组装sql查询语句

        DbManager db = x.getDb(((MyApplication) getApplicationContext()).getDaoConfig());        try {            List<Users>  list= db.selector(Users.class).where("age", ">", "12").findAll();            for (Users u : list) {                LogUtil.i(u.toString());            }        } catch (DbException e) {            e.printStackTrace();        }
运行截图如下所示,


其他有关查询操作就不多说了,最基本的其实是sql的拼写了!

3.下面看看删除操作。

删除数据
    void deleteById(Class<?> entityType, Object idValue) throws DbException;    void delete(Object entity) throws DbException;    void delete(Class<?> entityType) throws DbException;    int delete(Class<?> entityType, WhereBuilder whereBuilder) throws DbException;

(1).deleteById(Class<?> entityType, Object idValue)
根据表的主键进行单条记录的删除 

        DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            db.deleteById(Users.class,1);//参数一表示表对应的实体类,参数二表示记录主键        } catch (DbException e) {            e.printStackTrace();        }

运行前,数据表截图,有三条数据,


执行完,结果截图如下所示,


(2).delete(Object entity)的用法 
根据实体bean对表里面的一条或多条数据进行删除 

        DbManager db = x.getDb(((MyApplication) getApplicationContext()).getDaoConfig());        try {            List<Users>  list= db.selector(Users.class).where("age", ">", "12").findAll();            db.delete(list);        } catch (DbException e) {            e.printStackTrace();        }
执行完,结果截图如下所示,



(3).delete(Class<?> entityType) 
删除表格里面的所有数据,但是注意:表还会存在,只是表中数据清空了

   DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            db.delete(Users.class);        } catch (DbException e) {            e.printStackTrace();        }
(4).delete(Class<?> entityType, WhereBuilder whereBuilder) 
根据where语句的条件进行删除操作        

        DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            db.delete(Users.class, WhereBuilder.b("age",">","20"));        } catch (DbException e) {            e.printStackTrace();        }
(5).dropTable(Class<?> entityType) 
该方法是用来删除表

 DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            db.dropTable(Users.class);        } catch (DbException e) {            e.printStackTrace();        }
(6).dropDb() 
该方法是用来删除数据库

DbManager db=x.getDb(((MyApplication)getApplicationContext()).getDaoConfig());        try {            db.dropDb();        } catch (DbException e) {            e.printStackTrace();        }

4.更新数据

    void update(Object entity, String... updateColumnNames) throws DbException;    int update(Class<?> entityType, WhereBuilder whereBuilder, KeyValue... nameValuePairs) throws DbException;

(1).update(Object entity, String... updateColumnNames)

根据修改条件修改相应的数据。参数一要修改的数据,参数二要修改的字段名。

  DbManager db = x.getDb(((MyApplication) getApplicationContext()).getDaoConfig());        try {            Users u=db.selector(Users.class).where("age","=","30").findFirst();            u.setMobile("1234");            u.setName("zhangsan");            db.update(u,"mobile");            List<Users>  list= db.selector(Users.class).findAll();            for (Users u1 : list) {                LogUtil.i(u1.toString());            }        } catch (DbException e) {            e.printStackTrace();        }
运行后截图,


(2).update(Class<?> entityType, WhereBuilder whereBuilder, KeyValue... nameValuePairs)

根据修改条件修改相应的数据。参数一要修改的数据对应实体类,参数二要修改值的字段名,参数三、四...是新值

 DbManager db = x.getDb(((MyApplication) getApplicationContext()).getDaoConfig());        try {            db.update(Users.class,WhereBuilder.b().and("age","=","12"),new KeyValue("age",30));            List<Users>  list= db.selector(Users.class).findAll();            for (Users u : list) {                LogUtil.i(u.toString());            }        } catch (DbException e) {            e.printStackTrace();        }

运行后截图,


有关更加详细的介绍,请参考这篇文章,XUtils3框架的基本使用方法(二)。

PS: addColumn(Class<?> entityType, String column) 

    /**     * 添加一列,     * 新的entityType中必须定义了这个列的属性.     *     * @param entityType     * @param column     * @throws DbException     */    void addColumn(Class<?> entityType, String column) 
例如,tb_user表新增一列‘sex’,首先需要在实体类中增加相应的属性,以及实现它的get()和set()方法,然后执行下面的代码,

 DbManager db = x.getDb(((MyApplication) getApplicationContext()).getDaoConfig());        try {            db.addColumn(Users.class,"sex");        } catch (DbException e) {            e.printStackTrace();        }

运行后截图如下所示,


有关数据操作还有其他的方法,博文就不拓展了,望读者自行查阅。

由于篇幅原因,有关网络模块就放到下篇文章!有关网络部分,详情请看xUtils使用详解(二)。如果还想了解更多,可以去xUtils的github上看它们的sample。






2 0