xUtils3使用详解

2019-10-14 13:14:59

参考链接 xUtils3使用详解

一、xUtils简介:


xUtils是基于Afinal开发的目前功能比较完善的一个Android开源框架,官网:https://github.com/wyouflf/xUtils3


xUtils 包含了orm, http(s), image, view注解, 但依然很轻量级(246K), 并且特性强大, 方便扩展:

稳定的基石: AbsTask和统一的回调接口Callback, 任何异常, 即使你的回调方法实现有异常都会进入onError, 任何情况下onFinished总会让你知道任务结束了.

基于高效稳定的orm工具, http模块得以更方便的实现cookie(支持domain, path, expiry等特性)和 缓存(支持Cache-Control, Last-Modified, ETag等特性)的支持.

有了强大的http及其下载缓存的支持, image模块的实现相当的简洁, 并且支持回收被view持有, 但被Mem Cache移除的图片, 减少页面回退时的闪烁..

view注解模块仅仅400多行代码却灵活的支持了各种View注入和事件绑定, 包括拥有多了方法的listener的支持.

其他特性:

支持超大文件(超过2G)上传

更全面的http请求协议支持(11种谓词)

拥有更加灵活的ORM, 和greenDao一致的性能

更多的事件注解支持且不受混淆影响...

图片绑定支持gif(受系统兼容性影响, 部分gif文件只能静态显示), webp; 支持圆角, 圆形, 方形等裁剪, 支持自动旋转...

从3.5.0开始不再包含libwebpbackport.so, 需要在Android4.2以下设备兼容webp的请使用3.4.0版本.


总的来说。xutils主要有4个模块:注解模块,网络模块,图片加载模块,数据库模块。

二、使用前配置

1.使用Gradle构建时添加一下依赖即可:

compile 'org.xutils:xutils:3.4.0'

2.需要的权限:


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

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

三、初始化过程:

新建一个类MyApplication继承Application:

//初始化

public class MyApplication extends Application {

   public void onCreate() {

    super.onCreate();

    x.Ext.init(this);

    x.Ext.setDebug(true); //是否输出debug日志,开启debug会影响性能。

    }

}

四、注解模块

1.@ContentView:

加载当前的Activity布局时 将@ContentView加入到Activity的上方


2.@ViewInject

View注解的作用是代替我们写了findViewById这行代码,一般用于敏捷开发。


3.@Event事件注解

处理控件的各种响应事件,需要注意的是:

****

* 1. 方法必须私有限定,

* 2. 方法参数形式必须和type对应的Listener接口一致.

* 3. 注解参数value支持数组: value={id1, id2, id3}

* 4. type默认View.OnClickListener.class,即可故可以不写,直接写@Event(R.id.bt1)如果你想实现其余点击事件效果,只需要把type值进行修改


例:MainActivity


@ContentView(R.layout.activity_main)//加载布局xml

public class MainActivity extends AppCompatActivity {

    // view注解要求必须提供id,以使代码混淆不受影响。

    // 代价是增加了一次反射,每个控件都会。而反射是比较牺牲性能的做法,所以使用View注解算是有利有弊吧。

    @ViewInject(R.id.tv1)

    private TextView tv1;

 

 

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    x.view().inject(this); //绑定注解

    }

    

    //Event事件注解 ,点击bt1后弹出bt1测试

    @Event(value = {R.id.bt1},type = View.OnClickListener.class) 

    //方法需要用private

    private void onTest1click(View view){

 

    Toast.makeText(this,"bt1测试",Toast.LENGTH_LONG).show();

    }

    //长按事件

    @Event(value = R.id.Long,type = View.OnLongClickListener.class)

    private boolean testOnLongClickListener(View v){

    Toast.makeText(this,"btLong测试",Toast.LENGTH_LONG).show();  

    return true;

    }

}

例:fragment


@ContentView(R.layout.fragment_base)

public class BaseFragment extends Fragment {

    @Nullable

    @Override

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    return x.view().inject(this, inflater, container);

    }

    @Override

    public void onViewCreated(View v, @Nullable Bundle savedInstanceState) {

    super.onViewCreated(v, savedInstanceState);

    }

}

五、网络模块

xUtils3网络模块大大方便了在实际开发中网络模块的开发,xUtils3网络模块大致包括GET请求、POST请求、如何使用其他请求方式、上传文件、下载文件、使用缓存等功能。

Get请求

@Event(value = {R.id.bt2},type = View.OnClickListener.class)//注解

private void onTestGet(View view){

    String url ="http://10.203.0.4:8080/login"

    RequestParams params = new RequestParams(url);

    //params.setSslSocketFactory(...); // 设置ssl

    

    params.addQueryStringParameter("username","abc");

    params.addQueryStringParameter("password","123");

    x.http().get(params, new Callback.CommonCallback<String>() {

 

        public void onSuccess(String result) {

            Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();

            Log.i("JAVA", "onSuccess result:" + result);

 

        }

        //请求异常后的回调方法

        @Override

        public void onError(Throwable ex, boolean isOnCallback) {

        }

        //主动调用取消请求的回调方法

        @Override

        public void onCancelled(CancelledException cex) {

        }

        @Override

        public void onFinished() {

 

        }

    });

   

}

Post请求

@Event(R.id.bt2)

private void onTestPost(View v) {

    String url = "http://10.203.0.4:8080/login";

    RequestParams params = new RequestParams(url);

    params.addParameter("username", "abc");

    params.addParameter("password", "123");

    x.http().request(HttpMethod.PUT, params, new Callback.CommonCallback<String>() {

        @Override

        public void onSuccess(String result) {

        Toast.makeText(x.app(),result,Toast.LENGTH_LONG).show();

        }

        @Override

        public void onError(Throwable ex, boolean isOnCallback) {

        }

        @Override

        public void onCancelled(CancelledException cex) {

        }

        @Override

        public void onFinished() {

        }

    });

}

使用缓存

@Event(R.id.cache)

private void cache(View v) {

RequestParams params = new RequestParams(url);

params.setCacheMaxAge(1000*60); //为请求添加缓存时间

Callback.Cancelable cancelable = x.http().get(params, new Callback.CacheCallback<string>() {

    @Override

    public void onSuccess(String result) {

        Log.i("JAVA","onSuccess:"+result);

    }

    @Override

    public void onError(Throwable ex, boolean isOnCallback) {

    }

    @Override

    public void onCancelled(CancelledException cex) {

    }

    @Override

    public void onFinished() {

    }

    //result:缓存内容

    @Override

    public boolean onCache(String result) {

        //在setCacheMaxAge设置范围(上面设置的是60秒)内,如果再次调用GET请求,

        //返回true:缓存内容被返回,相信本地缓存,返回false:缓存内容被返回,不相信本地缓存,仍然会请求网络

        Log.i("JAVA","cache:"+result);

        return true;

    }

});

上传文件

@Event(R.id.upload)

private void upload(View v){

String path="/mnt/sdcard/Download/icon.jpg";

RequestParams params = new RequestParams(url);

params.setMultipart(true);

params.addBodyParameter("file",new File(path));

x.http().post(params, new Callback.CommonCallback<string>() {

    @Override

    public void onSuccess(String result) {

    }

    @Override

    public void onError(Throwable ex, boolean isOnCallback) {

    }

    @Override

    public void onCancelled(CancelledException cex) {

    }

    @Override

    public void onFinished() {

    }

});

下载文件

@Event(R.id.download)

private void download(View v){

url = "http://10.203.0.4:8080/server/nfctest.apk";

RequestParams params = new RequestParams(url);

//自定义保存路径,Environment.getExternalStorageDirectory():SD卡的根目录

params.setSaveFilePath(Environment.getExternalStorageDirectory()+"/myapp/");

//自动为文件命名

params.setAutoRename(true);

x.http().post(params, new Callback.ProgressCallback<file>() {

    @Override

    public void onSuccess(File result) {

        //apk下载完成后,调用系统的安装方法

        Intent intent = new Intent(Intent.ACTION_VIEW);

        intent.setDataAndType(Uri.fromFile(result), "application/vnd.android.package-archive");

        startActivity(intent);

    }

    @Override

    public void onError(Throwable ex, boolean isOnCallback) {

    }

    @Override

    public void onCancelled(CancelledException cex) {

    }

    @Override

    public void onFinished() {

    }

    //网络请求之前回调

    @Override

    public void onWaiting() {

    }

    //网络请求开始的时候回调

    @Override

    public void onStarted() {

    }

    //下载的时候不断回调的方法

    @Override

    public void onLoading(long total, long current, boolean isDownloading) {

        //当前进度和文件总大小

        Log.i("JAVA","current:"+ current +",total:"+total); 

    }

});

六、图片加载模块

xUtils3图片模块,重点在于加载图片的4个bind方法,loadDrawable与loadFIle用法和ImageOptions用法


bind的几个方法

void bind(ImageView view, String url);

 

void bind(ImageView view, String url, ImageOptions options);

 

void bind(ImageView view, String url, Callback.CommonCallback<Drawable> callback);

 

void bind(ImageView view, String url, ImageOptions options, Callback.CommonCallback<Drawable> callback);

 

Callback.Cancelable loadDrawable(String url, ImageOptions options, Callback.CommonCallback<Drawable> callback);

 

Callback.Cancelable loadFile(String url, ImageOptions options, Callback.CacheCallback<File> callback);

1.首先获取ImageView控件

@ViewInject(R.id.iv1)

ImageView image01;

@ViewInject(R.id.iv2)

ImageView image02;

...

2.定义图片网络地址或本地地址

String[] urls = {

        "http://img4.imgtn.bdimg.com/it/u=3182769660,1810895318&fm=23&gp=0.jpg",

        "http://img2.imgtn.bdimg.com/it/u=1278435851,1308167727&fm=23&gp=0.jpg",

        "http://img2.3lian.com/2014/f4/199/d/6.jpg",

        "http://pic1.win4000.com/wallpaper/4/584b9ea3a511c.jpg"

        ...

 

 

};  

3,通过ImageOptions.Builder().set方法设置图片的属性 然后通过bind方法加载图片,显示图片方法setImg()如下:

private void setImg() {

    /**

     * 通过ImageOptions.Builder().set方法设置图片的属性

     */

    ImageOptions options = new ImageOptions.Builder().setFadeIn(true).build(); //淡入效果

    //ImageOptions.Builder()的一些其他属性:

 

    //.setCircular(true) //设置图片显示为圆形

    //.setSquare(true) //设置图片显示为正方形

    //setCrop(true).setSize(200,200) //设置大小

    //.setAnimation(animation) //设置动画

    //.setFailureDrawable(Drawable failureDrawable) //设置加载失败的动画

    //.setFailureDrawableId(int failureDrawable) //以资源id设置加载失败的动画

    //.setLoadingDrawable(Drawable loadingDrawable) //设置加载中的动画

    //.setLoadingDrawableId(int loadingDrawable) //以资源id设置加载中的动画

    //.setIgnoreGif(false) //忽略Gif图片

    //.setParamsBuilder(ParamsBuilder paramsBuilder) //在网络请求中添加一些参数

    //.setRaduis(int raduis) //设置拐角弧度

    //.setUseMemCache(true) //设置使用MemCache,默认true

 

    /**

     * 加载图片的4个bind方法

     */

    x.image().bind(image01, urls[0]);

 

    x.image().bind(image02, urls[1], options);

 

    x.image().bind(image03, urls[2], options, 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() {

        }

    });

    x.image().bind(image04, urls[3], options, 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() {

        }

    });

 

    /**

     * loadDrawable()方法加载图片

     */

    Callback.Cancelable cancelable = x.image().loadDrawable(urls[4], options, new Callback.CommonCallback<Drawable>() {

        @Override

        public void onSuccess(Drawable result) {

            image05.setImageDrawable(result);

        }

        @Override

        public void onError(Throwable ex, boolean isOnCallback) {

        }

        @Override

        public void onCancelled(CancelledException cex) {

        }

        @Override

        public void onFinished() {

        }

    });

    //主动取消loadDrawable()方法

    //cancelable.cancel();

 

    /**

     * loadFile()方法

     * 应用场景:当我们通过bind()或者loadDrawable()方法加载了一张图片后,

     * 它会保存到本地文件中,那当我需要这张图片时,就可以通过loadFile()方法进行查找。

     * urls[0]:网络地址

     */

    x.image().loadFile(urls[0],options,new Callback.CacheCallback<File>(){

        @Override

        public boolean onCache(File result) {

            //在这里可以做图片另存为等操作

            Log.i("JAVA","file:"+result.getPath()+result.getName());

            return true; //相信本地缓存返回true

        }

        @Override

        public void onSuccess(File result) {

            Log.i("JAVA","file");

        }

        @Override

        public void onError(Throwable ex, boolean isOnCallback) {

        }

        @Override

        public void onCancelled(CancelledException cex) {

        }

        @Override

        public void onFinished() {

        }

    });

}


七:数据库模块的使用

首先进行配置DaoConfig:

DbManager.DaoConfig daoConfig = new DbManager.DaoConfig()

        //设置数据库名,默认xutils.db

        .setDbName("myapp.db")

        // 不设置dbDir时, 默认存储在app的私有目录.

        .setDbDir(new File("/sdcard")) // "sdcard"的写法并非最佳实践, 这里为了简单, 先这样写了.

        .setDbVersion(1)//数据库版本

 

        //设置是否允许事务,默认true

        //.setAllowTransaction(true)

 

        //设置表创建的监听

        .setTableCreateListener(new DbManager.TableCreateListener(){

 

            @Override

            public void onTableCreated(DbManager db, TableEntity<?> table) {

                Log.i("JAVA", "onTableCreated:" + table.getName());

            }

        })

 

        //设置数据库更新的监听

        .setDbUpgradeListener(new DbManager.DbUpgradeListener() {

            @Override

            public void onUpgrade(DbManager db, int oldVersion, int newVersion) {

 

            }

        })

        //设置数据库打开的监听

        .setDbOpenListener(new DbManager.DbOpenListener() {

            @Override

            public void onDbOpened(DbManager db) {

                //开启数据库支持多线程操作,提升性能

                db.getDatabase().enableWriteAheadLogging();

            }

        });

DbManager db = x.getDb(daoConfig);

然后创建数据库表Person的实体类:

/**

 * onCreated = "sql" sql:当第一次创建表需要插入数据时候在此写sql语句例:CREATE UNIQUE INDEX index_name ON person(id,name)

 */

@Table(name ="person",onCreated = "")

public class Person {

    /**

    * name = "id":数据库表中的一个字段

    * isId = true:是否是主键

    * autoGen = true:是否自动增长

     * property = "NOT NULL":添加约束

    */  

    @Column(name = "id",isId = true,autoGen = true,property = "NOT NULL")

    private int id;

    @Column(name = "c_name")

    private String name;

 

    public Person(String name) {

        this.name = name;

    }

 

    //默认的构造方法必须写出,如果没有,这张表是创建不成功的

    public Person() {

 

    }

 

    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;

    }

    @Override

    public String toString() {

        return "Person{" +

                "id=" + id +

                ", name='" + name + '\'' +

                '}';

    }

}

数据库的创建与删除以及数据的增删改查

数据库的创建

//数据库的创建

@Event(R.id.create_db)

private void createDB(View v) throws DbException {

    //用集合向Person表中插入多条数据

    ArrayList<Person> person = new ArrayList<>();

    person.add(new Person("张三"));

    person.add(new Person("李四"));

    person.add(new Person("赵六"));

 

    //db.save()方法不仅可以插入单个对象,还能插入集合

    db.save(person);

}

数据库的删除

//删除数据库

@Event(R.id.del_db)

private void delDB(View v) throws DbException {

 

    db.dropDb();

}

表的删除

@Event(R.id.del_table)

private void delTable(View v) throws DbException {

    db.dropTable(Person.class);

}

查询数据

@Event(R.id.select_table)

private void selelctDB(View v) throws DbException {

    //查询数据库表中第一条数据

    Person first = db.findFirst(Person.class);

    Log.i("JAVA",first.toString());

 

    //findAll():查询所有结果

    List<Person> personAll =db.findAll(Person.class);

    List<String > list = new ArrayList<String>();

    for(int i=0;i<personAll.size();i++){

        list.add(personAll.get(i).toString());

    }

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,list);

    lv1.setAdapter(adapter); 

 

    //添加查询条件进行查询

    WhereBuilder b = WhereBuilder.b();

    b.and("id",">",2); //构造修改的条件

    b.and("id","<",4);

    List<Person> all = db.selector(Person.class).where(b).findAll();

    //第二种写法:

    List<Person> all2 = db.selector(Person.class).where("id",">",2).and("id","<",4).findAll();

    for(Person person :all){

        Log.i("JAVA",person.toString());

    }

}

修改数据

//修改表中数据

@Event(R.id.update_table)

private void updateTable(View v) throws DbException {

    //第一种写法:

    Person first = db.findFirst(Person.class);

    first.setName("张三01");

    db.update(first, "c_name"); //c_name:表中的字段名

    //第二种写法:

    WhereBuilder b = WhereBuilder.b();

    b.and("id", "=", first.getId()); //构造修改的条件

    KeyValue name = new KeyValue("c_name", "张三02");

    db.update(Person.class, b, name);

 

    //第三种写法:

    first.setName("张三修改");

    db.saveOrUpdate(first);

    Toast.makeText(this,"修改成功",Toast.LENGTH_LONG).show();

}

删除数据

@Event(R.id.del_table_data)

private void delTableData(View v) throws DbException {

    //第一种写法:

    db.delete(Person.class); //child_info表中数据将被全部删除

    //第二种写法,添加删除条件:

    WhereBuilder b = WhereBuilder.b();

    b.and("id",">",2); //构造修改的条件

    b.and("id","<",4);

    db.delete(Person.class, b);

}



  • 2021-01-21 13:52:36

    node.js使用Nodemailer发送邮件

    常常看到一些网站有邮箱获取验证码验证注册或者修改密码等,今天也来了解一下在nodejs + express怎么发送电子邮件。使用模块Nodemailer。这里以qq邮箱举例子。

  • 2021-01-21 13:55:53

    Mongodb字段更新$unset操作符

    当使用$操作符匹配任何数组元素,$unset替换指定的元素为null而不是删除掉指定的元素,此行为保持数组大小和位置一直;

  • 2021-01-22 08:30:02

    Android IO简化之Okio库

    如果之前有使用过Okhttp,那么你一定知道底层的IO读取是由square公司开发的Okio库。它补充了Java.io和java.nio的不足,以便能够更加方便,快速的访问、存储和处理你的数据。而在一般的开发中,我们也可以使用Okio来做IO读写,非常方便深得我心

  • 2021-01-22 21:56:48

    emcc生成wasm,wast,bc文件的方法

    Emscripten实现把C/C++文件转成wasm,wast(wasm的可读形式),llvm字节码(bc格式),ll格式(llvm字节码的可读形式)的步骤。

  • 2021-01-22 21:59:34

    emcc编译与部分重要参数选取

    C/C++代码通过emcc编译为字节码,然后根据不同的目标编译为asm.js或wasm。emcc和gcc编译选项类似,例如-s OPTIONS=VALUE、-O等。另外为了适应Web环境,emcc增加了一些特有的选项,如–pre-js 、–post-js 等。

  • 2021-01-22 22:01:19

    Emscripten Compiler Frontend (emcc)

    The Emscripten Compiler Frontend (emcc) is used to call the Emscripten compiler from the command line. It is effectively a drop-in replacement for a standard compiler like gcc or clang.

  • 2021-01-22 22:21:41

    emcc编译命令介绍

    这个输入文件file,既可以是clang可以编译的C/C++语言,也可以是二进制形式的llvm bitcode或者人类可读形式的llvm assembly文件。