Xutils-Android中数据存储和网络传输的框架

待解决:1.自处理复杂的sql语句

2.xutils自定义类型的属性

Xutils 数据库存储自定义类型和自定义数据类型集合 - 简书 (jianshu.com)

(1条消息) xUtils系列之DbUtils-保存自定义类型_轻度强迫症患者的博客-CSDN博客



(1条消息) xUtils 3 中,如何存储自定义实体类字段类型_WymanWong的博客-CSDN博客

一.引入Xutils包

1.首先需要引入Xutils包,在buil.gradle中添加如下内容:

implementation 'org.xutils:xutils:3.9.0'

2.在AndroidManifest.xml文件中添加网络权限等

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

3.然后需要在自定义Application中添加初始化内容:(放在onCreate方法中)

x.Ext.init(this);//注册Xutils
//x.Ext.setDebug(false); // 是否输出debug日志,开启debug会影响性能,暂时未用到
//自定义特殊类型的转换器,
//ColumnConverterFactory.registerColumnConverter(GeometryField.class, new GeometryColumnConverter());
initDBManager();//数据库模块使用的,自定义的一个用来初始化数据库的函数

二.数据库模块-DbUtils

1.创建数据库

//数据库初始化
    private void initDBManager() {
        //data/data/com.iot.gis/databases/gis_report.db
        File dbFile = this.getDatabasePath("gis_report.db");
        //getDatabasePath函数是用来获取右侧手机路径:/data/user/0/应用包名/databases/参数名 下的文件
        boolean dbFileOk = copyDb(dbFile);
        //因为项目需要自带数据,所以就把数据都放到一个SQLite的数据库文件中了,之后把db文件放到了assets文件夹下面。
        //copyDb函数然后判断手机路径下是否有db文件,如果没有,就把assets下的db文件数据,复制到对应目录下,如果有,则表示已经复制过了,就不需要创建了。
        if (!dbFileOk) {
            Logger.eTag(TAG, ResUtils.getString(R.string.db_file_not_exists));
            return;
        }

        DbManager.DaoConfig daoConfig = new DbManager.DaoConfig()
                .setDbName("gis_report.db")//设置数据库名称
                .setDbVersion(1)//设置数据库版本
                .setAllowTransaction(true)//设置是否允许事务,默认true
                .setDbDir(dbFile.getParentFile())// 不设置dbDir时, 默认存储在app的私有目录.
                .setDbOpenListener( new DbManager.DbOpenListener() {//设置数据库打开的监听
                            @Override
                            public void onDbOpened(DbManager db) {
                                //开启数据库支持多线程操作,提升性能,对写入加速提升巨大
                                db.getDatabase().enableWriteAheadLogging();
                            }
                        }
                )
                //下面这2个暂时还没用到
               /* .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) {

                    }
                })*/
                ;
        try {
            db = x.getDb(daoConfig);
            //gisDB = new GISDbManager(db);//gisDB是学长创建的用来查询复杂的sql语句的,里面还包含了事务
            Logger.iTag(TAG, db.getDatabase().getPath());
        } catch (DbException e) {
            Logger.eTag(TAG, e);
        }

    }

    private boolean copyDb(File dbFileTargetPath) {
        try {
            if (!dbFileTargetPath.exists()) {   //判断该文件是否存在于手机中
                InputStream dbFileIS = this.getAssets().open("gis_report.db");
                //以数据流的形式获取左侧AS中assets文件夹中对应文件名的内容
                return FileIOUtils.writeFileFromIS(dbFileTargetPath, dbFileIS);
                //将读取的输入流写入文件
            }
        } catch (IOException e) {
            Logger.eTag(TAG, e);
            return false;
        }
        return true;
    }

2.创建数据库中一个表对应的实体类

import org.xutils.db.annotation.Column;
import org.xutils.db.annotation.Table;
//数据库中表的实体类
@Table(name = "Common_Using_rock_soil_sample")  //确定表名
public class SampleModel {
    //样本ID
    @Column(name = "sample_id", isId = true, autoGen = false)//isId为true代表为主键,autoGen为true代表自增,不写autoGen这个属性,默认是自增长的属性
    //@Column(name = "sample_id",property ="NOT NULL")//添加约束条件,这里不能为空。
    //如果普通属性没有加上@Column标签,生成表中的字段就不会包含该属性
    public long sample_id;
    //项目ID
    @Column(name = "project_id")//name是用来设置列名的
    public long project_id;
    //样本编号
    @Column(name = "sample_code")
    public String sample_code;
    //样本类型
    @Column(name = "sample_type")
    public String sample_type;
    //动作关联ID
    @Column(name = "action_relation_id")
    public long action_relation_id;
    //版本号
    @Column(name = "sync_version_number")
    public long sync_version_number;
    //备注
    @Column(name = "remark")
    public String remark;
    //野外名称
    @Column(name = "field_name")
    public String field_name;
    //勘调对象ID
    @Column(name = "survey_target_id")
    public long survey_target_id;

    public SampleModel() {//必须要有无参构造,否则创建表不成功
    }
    //有参构造方法和相关set、get方法根据自己的需求来,使用AS快捷键创建会方便很多
}

3.对数据表进行操作

 //插入
    public static void insertSamples(List<SampleModel> sampleModels) {

        for (SampleModel sampleModel : sampleModels) {
            try {
                GISApplication.db.saveOrUpdate(sampleModel);    //更新保存单个样例***主要用saveOrUpdate
            } catch (DbException e) {
                Log.e("eee", "samplemodel");
            }
        }

        try {
            GISApplication.db.save(sampleModels);//保存实体类或实体类的List到数据库
            //db.replace(list);保存或更新实体类或实体类的List到数据库, 根据id和其他唯一索引判断数据是否存在
            //db.saveOrUpdate(list);保存或更新实体类或实体类的List到数据库, 根据id对应的数据是否存在.
            //db.saveBindingId(list);保存实体类或实体类的List到数据库,如果该类型的id是自动生成的, 则保存完后会给id赋值.
            /**
             * 1.如果在你建表的时候你的主键设置成自增长,那么你在插入数据的时候直接调replace方法就可以了,
             *   但是saveOrUpdate只能达到插入的效果,达不到更新原有数据的效果.
             * 2.如果在你建表的时候你的主键设置成不是自增长,replace方法当然可以插入,saveOrUpdate方法既可以插入也可以达到更新的效果
             */
        } catch (DbException e) {
            Log.e("eee", "samplemodels");
        }
    }
    //查询
    public static List<SampleModel> selectSamples() {
        try {
            SampleModel sampleModel1 = GISApplication.db.findById(SampleModel.class, 2);//根据主键来查找表里的数据
            SampleModel sampleModel2 = GISApplication.db.findFirst(SampleModel.class);//返回当前表的第一条数据
            //查询所有数据
            List<SampleModel> all = GISApplication.db.findAll(SampleModel.class);
            //按条件查找,查询年龄大于15的
            List<DbModel> dbModelAll = GISApplication.db
            .findDbModelAll(new SqlInfo("select * from student where age > 15"));//findDbModelFirst
            for (int i = 0; i < dbModelAll.size(); i++) {
                DbModel dbModel = dbModelAll.get(i);
                String name = dbModel.getString("name");
                Log.i("tag", "查询的数据: name=" + name);
            }
            //第二种条件查找,我用的这种
            List<SampleModel> all1 = GISApplication.db.selector(SampleModel.class)//***主要用这种查询条件
                    .where("age", ">", 14)
                    .and("age", "<", 16)
                    .findAll();//.findFirst();.count();
            /**List<DbModel> list = db.selector(Child.class)    //复杂的参考样例
             .where("age", "<", 18)
             .groupBy("parentId")
             .having(WhereBuilder.b("COUNT(parentId)", ">", 1))
             .select("parentId, COUNT(parentId) as childNum")
             .findAll();**/
            //和上面那种应该是等价的
            WhereBuilder b = WhereBuilder.b();
            b.and("id",">",2); //构造修改的条件
            b.and("id","<",4);
            List<SampleModel> all2 = GISApplication.db.selector(SampleModel.class)
            .where(b).findAll();
            //第三种
            List<SampleModel> all3 = GISApplication.db.selector(SampleModel.class)
            .expr("age>14 and age<17").findAll();
            if (all1 == null) {
                all1 = new ArrayList<>();
            }
            return all1;
        } catch (DbException e) {
            return new ArrayList<>();
        }
    }
    //删除
    public static void deleteSamples() {
            try {
                //第一种,根据主键来删除
                GISApplication.db.deleteById(SampleModel.class,5);//删除主键为5的值

                //第二种方法,找到符合条件的第一条数据  .findAll()就是找所有符合条件的了
                SampleModel student = GISApplication.db.selector(SampleModel.class)
                .where("name", "=", "学生11").findFirst();
                GISApplication.db.delete(student);//先找到,再删除 ,需要判断为不为空

                //第三种,删除那name=学生9 且 sex=女 的数据
                GISApplication.db.delete(SampleModel.class, WhereBuilder
                        .b("name","=" ,"学生9")
                        .and("sex","=","女"));
                //第二种写法,添加删除条件:
                WhereBuilder b = WhereBuilder.b();
                b.and("id",">",2); //构造修改的条件
                b.and("id","<",4);
                GISApplication.db.delete(SampleModel.class, b);
                //第四种,删除所有数据,但是表还在
                GISApplication.db.delete(SampleModel.class);

                //db.dropTable(Student.class);删除表
                //db.dropDb();删除数据库

            } catch (DbException e) {
                e.printStackTrace();
            }

    }

三.网络模块-HttpUtils

数据传输他这里有同步请求和异步请求,同步请求需要自己单独再开一个线程,我这里认为如果你需要同时传多个数据对应多个接受数据的时候,把这几个同步传输,然后放到一个子线程中。

1.在Thread中的同步请求

new Thread(new Runnable() {
            @Override
            public void run() {
                ///相关传输数据的函数
            getActivity().runOnUiThread(new Thread(() -> {
       
            }));
            }
        }).start();
///下面这种是用lamdba表达式
new Thread(() -> {
               ///相关传输数据的函数
            postData();
            getActivity().runOnUiThread(new Thread(() -> {
       
            }));
        }).start();

2.同步上传数据 

 public void postData(String POST_Url){
        RequestParams params = new RequestParams(POST_Url); //POST_Url为post上传的 地址+函数名称
        JSONObject js_request = new JSONObject();//服务器需要传参的json对象
        js_request.put("geom", "XXX");//根据实际需求添加相应键值对,put是一个一个添加的
        Map<String, Object> attrs=new HashMap<>();
        attrs.put("eguid", "1");
        attrs.put("survey_target_id", 2);
        js_request.putAll(attrs);   //添加一群键值对
        params.setAsJsonContent(true);  //以json形式提交body参数
        //params.setAsJsonArrayContent(true); //以json array形式提交body参数
        params.setBodyContent(js_request.toString());//设置body参数中的内容
        try {
            String data = x.http().postSync(params, String.class);       //JSONObject.class
            //data
        } catch (Throwable throwable) {
            //处理报错
        }
    }

//参考地址:http://42.192.6.203:9904/api/EntityAttributeTable/postBo?<{"delete_flag":0,"sync_version_number":21}>

3.同步下载数据

 public void getData(String GET_Url){
        RequestParams params2 = new RequestParams(GET_Url); //GET_Url为get下载的 地址+函数名称
        params2.addQueryStringParameter("work_point_id", 1);
        params2.addQueryStringParameter("p", 2);//这个可以添加多个,通过类的反射机制,自动用for循环添加类的各个属性
        //下面这2个参数可能主要还是为了实现断点下载,虽然好像暂时没用到?
        params2.setAutoResume(true);//设置是否在下载是自动断点续传,默认的也是为true,可以不设置
        params2.setCancelFast(true);    是否可以被立即停止
        try {
            String data = x.http().getSync(params2, String.class); 
            //data是获取到的数据,如果是json数据,可以采用对应的方法转换成对应的类
        } catch (Throwable throwable) {
            //报错,进行处理
        }
    }
//参考地址:http://42.192.6.200:9900/api/EntityAttributeTable/getBou?id=1&name="2"

4.同步上传文件

public void postFile(String POST_Url,String path){
        RequestParams params = new RequestParams(POST_Url); //POST_Url为post上传的 地址+函数名称
        //传输文件
        params.setMultipart(true);
        params.addBodyParameter("file", new File(path));    //适用于POST请求方式;添加到Body体的参数。
        params.setAutoRename(true);//文件的自动命名,服务器端设置的重复的文件名会覆盖掉
        try {
            File data = x.http().postSync(params, File.class);
            //Log.e("eee2", data.toString());
            //如果是请求json,使用String.class,如果下载文件,使用File.class。这里上传的感觉用String也可以?
        } catch (Throwable throwable) {
            //报错处理
        }
    }

//参考地址:http://42.192.6.200:9900/api/EntityAttributeTable/PostFile?<file=/storage/emulated/0/YingHe/sketchPhoto/2022-03-30_092143.png>

5.同步下载文件

public void getFile(String GET_Url,String path){    //path是要保存到手机中的地址,参考:/storage/emulated/0/Pictures/1/224.jpg
        RequestParams params2 = new RequestParams(GET_Url); //GET_Url为get下载的 地址+Photos+文件名
        params2.setMultipart(true);//传输文件,使用multipart表单
        params2.setSaveFilePath(path);//设置下载文件时文件保存的路径和文件名
        try {
            File data = x.http().getSync(params2, File.class);
            //Log.e("eee2", data.getAbsolutePath());
        } catch (Throwable throwable) {
           //报错,进行处理
        }
    }
//参考地址:http://42.192.6.203:9904/Photos/2022-03-30_092143.png?

6.上传数据还有另一种格式

public void postFileName(){
        RequestParams requestParams = new RequestParams(POST_FileName);
        Log.e("eee1","eee1");
        requestParams.addBodyParameter("TableName", "eee");
        requestParams.addBodyParameter("ProjectId", 2);
        requestParams.addBodyParameter("photoFileName", "223.png");
        requestParams.setAutoResume(true);
        requestParams.setCancelFast(true);
        try {
            String data = x.http().postSync(requestParams, String.class);
            Log.e("eee2",data);
        }catch (Throwable throwable) {
            throwable.printStackTrace();
            Log.e("eee3","eee3");
        }
    }



/**
 JSONObject  jsonObject;
                try {
                    jsonObject = x.http().getSync(params, JSONObject.class);
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
**/

7.异步传输

暂时还不太会

参考网址:

GitHub - wyouflf/xUtils3: Android orm, bitmap, http, view inject...

Android Xutils3 完全解析 - 上七旗娃儿 - 博客园 (cnblogs.com)

(1条消息) XUtils3的使用(Get,Post,断点下载,上传文件,数据库,bitmap的下载与缓存)_Dawn仧的博客-CSDN博客_xutils3上传bitmap

xUtils使用详细介绍 - favour - 博客园 (cnblogs.com)

Android xUtils3.0使用手册(一)- 基础功能使用 - 大西瓜3721 - 博客园 (cnblogs.com)

Android使用xUtils3.0实现文件上传_Android_萬仟网 (10qianwan.com)

xUtils 3.0 post使用详解 - 丶贰九 - 博客园 (cnblogs.com)

xUtils3 注解模块 - Vitality - 博客园 (cnblogs.com)

public  void postData()
    {
        JSONObject js_request = new JSONObject();//服务器需要传参的json对象
        js_request.put("key", "value");//根据实际需求添加相应键值对
        js_request.put("key1", "value1");
        js_request.put("key2", "value2");

        RequestParams params = new RequestParams("http://www.baidu.com");
        params.setAsJsonContent(true);
        params.setBodyContent(js_request.toString());
        //params.addBodyParameter("pageNo","1");
        //params.addBodyParameter("pageSize","20");

        
        //post这里改成request就一样
        x.http().post(params, new Callback.CacheCallback<String>() {//发起传参为json的post请求,
            // Callback.CacheCallback<String>的泛型为后台返回数据的类型,
            // 根据实际需求更改
            @Override
            public boolean onCache(String result) {
                return false;
            }

            @Override
            public void onSuccess(String result) {

                //此处请求成功后的逻辑
                Log.e("eee2",result);
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {
            Log.i("tag", "请求异常");
            }

            @Override
            public void onCancelled(CancelledException cex) {
            Log.i("tag", "取消请求的回调方法");
            }

            @Override
            public void onFinished() {
            Log.i("tag", "请求完成,并不一定是请求成功,断开了连接就会执行该方法");
            }
        });
    }

public void get(){
RequestParams params = new RequestParams(url);
    params.addQueryStringParameter("username","abc");
    params.addQueryStringParameter("password","123");
    Callback.Cancelable cancelable = x.http().get(params, new Callback.CommonCallback<string>() {
        @Override
        public void onSuccess(String result) {
            Log.i("JAVA", "onSuccess result:" + result);
       
        }
        //请求异常后的回调方法
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        //主动调用取消请求的回调方法
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {
        
        }
    });

}


public void posfile(){
    String path="/mnt/sdcard/Download/icon.jpg";
        RequestParams params = new RequestParams("地址");
        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() {
            }
        });
}

public void getfile(){
    RequestParams params = new RequestParams(url);
    //自定义保存路径,Environment.getExternalStorageDirectory():SD卡的根目录
    params.setSaveFilePath(Environment.getExternalStorageDirectory()+"/myapp/");
    //自动为文件命名
    params.setAutoRename(true);
    x.http().get(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");
            getActivity().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); 
        }
    });
}

//使用缓存
public void cache(){
    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;
        }
    });
}

断点下载:

pulblic  void duan(){
//设置请求参数
        RequestParams params = new RequestParams(pathApk);
        params.setAutoResume(true);//设置是否在下载是自动断点续传
        params.setAutoRename(false);//设置是否根据头信息自动命名文件
        params.setSaveFilePath("/sdcard/xutils/xUtils_1.avi");
        params.setExecutor(new PriorityExecutor(2, true));//自定义线程池,有效的值范围[1, 3], 设置为3时, 可能阻塞图片加载.
        params.setCancelFast(true);//是否可以被立即停止.
        //下面的回调都是在主线程中运行的,这里设置的带进度的回调
        cancelable = x.http().get(params, new Callback.ProgressCallback<File>() {
            @Override
            public void onCancelled(CancelledException arg0) {
                Log.i("tag", "取消"+Thread.currentThread().getName());
            }
 
            @Override
            public void onError(Throwable arg0, boolean arg1) {
                Log.i("tag", "onError: 失败"+Thread.currentThread().getName());
                progressDialog.dismiss();
            }
 
            @Override
            public void onFinished() {
                Log.i("tag", "完成,每次取消下载也会执行该方法"+Thread.currentThread().getName());
                progressDialog.dismiss();
            }
 
            @Override
            public void onSuccess(File arg0) {
                Log.i("tag", "下载成功的时候执行"+Thread.currentThread().getName());
            }
 
            @Override
            public void onLoading(long total, long current, boolean isDownloading) {
                if (isDownloading) {
                    progressDialog.setProgress((int) (current*100/total));
                    Log.i("tag", "下载中,会不断的进行回调:"+Thread.currentThread().getName());
                }
            }
 
            @Override
            public void onStarted() {
                Log.i("tag", "开始下载的时候执行"+Thread.currentThread().getName());
                progressDialog.show();
            }
 
            @Override
            public void onWaiting() {
                Log.i("tag", "等待,在onStarted方法之前执行"+Thread.currentThread().getName());
            }
 
        });


}

添加到请求body体的参数, 只有POST, PUT, PATCH, DELETE请求支持. 

四.注解模块-HttpUtils

暂未使用,用时百度。

五.图片模块-HttpUtils

暂未使用,用时百度。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值