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-06 10:47:29

    date-fns日期工具的使用方法详解

    isToday() 判断传入日期是否为今天 isYesterday() 判断传入日期是否为昨天 isTomorrow() 判断传入日期是否为 format() 日期格式化 addDays() 获得当前日期之后的日期 addHours() 获得当前时间n小时之后的时间点 addMinutes() 获得当前时间n分钟之后的时间 addMonths() 获得当前月之后n个月的月份 subDays() 获得当前时间之前n天的时间 subHours() 获得当前时间之前n小时的时间 subMinutes() 获得当前时间之前n分钟的时间 subMonths() 获得当前时间之前n个月的时间 differenceInYears() 获得两个时间相差的年份 differenceInWeeks() 获得两个时间相差的周数 differenceInDays() 获得两个时间相差的天数 differenceInHours() 获得两个时间相差的小时数 differenceInMinutes() 获得两个时间相差的分钟数

  • 2019-12-06 10:49:39

    npm 查看源 换源

    npm,cnpm,查看源,切换源,npm config set registry https://registry.npmjs.org

  • 2019-12-06 11:01:31

    npm发布包流程详解 有demo

    npm发布包步骤,以及踩过的坑(见红颜色标准): 1.注册npm账号,并完成Email认证(否则最后一步提交会报Email错误) 2.npm添加用户或登陆:npm adduser 或 npm login

  • 2019-12-06 13:16:18

    vue mixins组件复用的几种方式

    最近在做项目的时候,研究了mixins,此功能有妙处。用的时候有这样一个场景,页面的风格不同,但是执行的方法,和需要的数据非常的相似。我们是否要写两种组件呢?还是保留一个并且然后另个一并兼容另一个呢? 不管以上那种方式都不是很合理,因为组件写成2个,不仅麻烦而且维护麻烦;第二种虽然做了兼容但是页面逻辑造成混乱,必然不清晰;有没有好的方法,有那就是用vue的混合插件mixins。混合在Vue是为了提出相似的数据和功能,使代码易懂,简单、清晰。

  • 2019-12-06 13:26:30

    vue的mixins混入合并规则

    混入minxins:分发vue组件中可复用功能的灵活方式。混入对象可以包含任意组件选项。组件使用混入对象时,所有混入对象的选项将混入该组件本身的选项。

  • 2019-12-06 16:50:34

    Intellij idea 如何关闭无用的提示

    Linux:Settings —> Editor —> Inspections —> General —> Duplicated Code Mac:Preferences --> Editor —> Inspections —> General —> Duplicated Code fragment 将对应的勾去掉。

  • 2019-12-09 15:36:56

    神秘的 shadow-dom 浅析,shadow-root

    顾名思义, shadow-dom,直译的话就是 影子dom ?我觉得可以理解为潜藏在黑暗中的 DOM 结构,也就是我们无法直接控制操纵的 DOM 结构。前端同学经常用开发者工具的话,查看 DOM 结构的时候,肯定看到过下面这样的结构:

  • 2019-12-10 11:13:50

    前端实战-基于Nuxt的SVG使用

    虽然我们在日常开发的时候,在使用iview 或者element ui等组件时,通常会包含一些常用icon;但是在面对一些特定的需求时,或者自己想high一下,这些通用的icon并不能很好的满足我们。这个时候我们可能会拿到一些SVG适量图,但是怎么去使用这些矢量图呢。