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);

}



  • 2019-12-10 16:21:05

    display:flex的子元素无法设置宽度

    子元素有个flex-shrink属性,表示在父元素宽度不够的情况下是自动收缩不?0表示不自动收缩,1表示自动收缩;所以将子元素(图片)添加属性:flex-shrink:0;即

  • 2019-12-10 21:14:11

    axios文件上传功能+formData

    在项目中使用axios上传文件,记得new一个纯净的axios或者考虑用ajax请求。因为axios在项目估计已经用了全局配置请求头等信息,这里的配置可能被全局请求头拦截,导致请求失败。 2.1构造formData 作者:exmexm 链接:https://www.jianshu.com/p/9c708a47d8a5 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 2019-12-11 16:04:15

    CSS中的 “var()” 和 “:root”

    var() var()函数可以代替元素中任何属性中的值的任何部分。var()函数不能作为属性名、选择器或者其他除了属性值之外的值。(这样做通常会产生无效的语法或者一个没有关联到变量的值。)

  • 2019-12-11 16:18:51

    npm发布vue组件

    开发之前先看看官网的 开发规范 我们开发的之后期望的结果是支持 import、require 或者直接使用 script 标签的形式引入,就像这样

  • 2019-12-11 16:21:00

    .vue文件 加scoped 样式不起作用

    在vue组件中,为了使样式私有化(模块化),不对全局造成污染,在style标签上添加scoped属性,以表示它只属于当下的模块。但是要慎用,因为在我们需要修改公共组件(第三方库或者项目中定制的组件)的样式的时候,scoped会造成很多困难,组要增加额外的复杂度。

  • 2019-12-11 16:22:04

    Vue中的scoped和scoped穿透,scoped原理

    在Vue文件中的style标签上有一个特殊的属性,scoped。当一个style标签拥有scoped属性时候,它的css样式只能用于当前的Vue组件,可以使组件的样式不相互污染。如果一个项目的所有style标签都加上了scoped属性,相当于实现了样式的模块化。