【Android】GreenDao 3.X 结合Volley以及Gson、ImageLoader实现数据存储

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaxiazaizai01/article/details/53118748

关于GreenDao的优点已经不用再说了,关于第三方数据库框架有很多,相对于Android系统本身的SQLite以及其它第三方而言,我感觉GreenDao使用更方便,体积小、速度更快。网上大多是关于GreenDao之前版本的介绍,关于3.0+新版的介绍不多。GreenDao新版改动还是挺大的,之前版本使用起来比较复杂,需要新建项目,然后再项目中配置各个实体的字段等相关属性,然后生成实体以及DAO操作相关的一些类。而GreenDao3.0及其以后是通过注解的方式定义实体类,并且是通过插件来生成相应代码。
数据库应用的场景也非常多,比如:电商类app中最常见的就是搜索的历史记录等等,使用数据库进行增删改查就相对方便多了,并且GreenDao提供了数据库加密设置,更加安全。
先来张效果图
这里写图片描述

再看下我们通过@Entity设置的实体类中的字段在数据库中对应的字段以及相应的存储数据
这里写图片描述

这里说明一下:此demo演示的场景是,有网时,联网请求数据,请求成功后将数据保存到GreenDao数据库,没网时,则从数据库中取数据。访问数据接口采用的是Volley框架,当然了你还可以使用OkHttp等,采用Gson解析方式,或者采用阿里的FastJson,两种解析方式差不多,在设计实体类的时候要注意下,字段什么的要跟服务端给你的json串中字段相同,从而操作更加简单。其中请求接口返回三条数据,这里解释下为什么第二条数据没有图片,这不是Bug。。。这是因为第二条数据压根就没给图片,就是这么任性,所以说有时间还是要学学后端的,这样就可以自己写服务端了,测试起来也方便。由于接口返回数据比较多,这里主要是演示GreenDao3.0X数据库保存数据,这里我只是解析了部分字段,保存的时候也只是保存了两文本字段,图片相对麻烦就没有保存,正式开发的话是保存到缓存中的。

下面还是说下怎么使用新版GreenDao3.X 吧,先给出官网github地址:https://github.com/greenrobot/greenDAO

首先我们需要在Gradle中添加如下配置

//首先在project的gradle文件中引入greenDAO插件
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.0.0'
    }
}

//然后在module的gradle文件中添加greenDAO的插件,并引入相关类库
apply plugin: 'org.greenrobot.greendao'
dependencies {
    compile 'org.greenrobot:greendao:3.0.0'
}

最新版本是3.2.0,这里说下为什么我没用3.2.0版本,因为使用此版本编译一直报可奇怪的错,这里选用3.0.0也一样,主要就是为了说明跟之前2.X版本的区别。其中,我们看到classpath ‘org.greenrobot:greendao-gradle-plugin:3.0.0’这是添加插件的,用插件生成我们的相应代码用的。

同时,我们还可以配置当插件根据我们所定义的实体类自动生成的DaoMaster、DaoSession以及实体类相对应的XXXDAO类文件的存放目录。

greendao {
    schemaVersion 1
    daoPackage 'com.example.testproject.greendao.gen'
    targetGenDir 'src/main/java'
}

说明:schemaVersion:表示指定数据库schema版本号,如果需要数据库升级,可以在这里修改数据库最新版本号。 daoPackage:表示生成的这些类文件在哪个包下面(默认为你的entity所在的包名)。 targetGenDir:就是上面所说的制定这些类文件所在的目录,这里我们设置跟我们代码目录相同,都是在java目录中,方便查看。

我们接下来写我们的实体类(ProductBean),这些实体类中的字段是要写进数据库的,就相当于一张表(ProductBean表)。写完之后我们选择Build–>Make Project,剩下的就交给插件了,就会自动帮我们生成(每次修改字段啥的,不要忘记Build–>Make Project), 如下图所示:

这里写图片描述

/**
 * 实体类,存储到数据库
 */
@Entity
public class ProductBean {
    private Long id;
    @Property(nameInDb = "url")
    private String picUrl;
    @Property(nameInDb = "title")
    private String proTitle;
    @Property(nameInDb = "info")
    private String proInfo;
    @Property(nameInDb = "proId")
    @Id
    private Long proId;
}    

这里有几点需要注意:GreenDao3.X 要求主键必须是Long或者long类型的。这里由于接口请求的数据中含有一个id,所以我就用这个id作为主键,当然这个id是String类型的,需要转换下。@Id:表示作为主键 @Property(nameInDb = “url”):表示该字段在数据库中的字段名称,还有很多属性,大家可以到官网上去了解,最后别忘了在定义实体类上面要加上@Entity因为插件要根据它生成相应的DAO。定义的有些字段是没用到的,大家测试的时候也可以自行删除。

GreenDao3.X 配置完了,接下来就是撸代码了。官方推荐将DaoMaster 对象的方法放到 Application 层,这样将避免多次创建生成 Session 对象。下面看下我们的application

/**
 * 自定义MyApplication
 */
public class MyApplication extends Application {

    private static MyApplication myApplication;
    public RequestQueue requestQueue;

    private static DaoMaster daoMaster;
    private static DaoSession daoSession;

    @Override
    public void onCreate() {
        super.onCreate();
        myApplication = this;
        //创建队列
        requestQueue = Volley.newRequestQueue(this);
    }

    public static DaoMaster getDaoMaster(Context context){
        if(daoMaster == null){
            DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context,"mydata-db",null);
            daoMaster = new DaoMaster(helper.getWritableDatabase());
        }
        return daoMaster;
    }

    public static DaoSession getDaoSession(Context context){
        if(daoSession == null){
            if(daoMaster == null){
                daoMaster = getDaoMaster(context);
            }
            daoSession = daoMaster.newSession();
        }
        return daoSession;
    }

    public static MyApplication getApplication() {
        return myApplication;
    }
}

关于增、删、改、查,这些就比较简单了。这里简单说下,首先,我们先获取DaoSession,从而来操作数据库。查看源代码可以看到,GreenDao的一些例如:增、删等操作内部已经封装处理了事务回滚等操作,我们使用起来更加方便。

ProductBeanDao dao = MyApplication.getDaoSession(MainActivity.this).getProductBeanDao();

1. 插入(批量添加时属于耗时操作,GreenDao提供的有异步操作方法runInTx()方法)

ProductBean productBean = new ProductBean(null,null,productData.getName(),productData.getInfo(),Long.parseLong(productData.getId()));

dao.insert(productBean);
//dao.insertOrReplace(productBean);

//批量添加的情况(注意try的位置)
final List<ProductBean> lists = new ArrayList<ProductBean>();
for(int i=0;i<20;i++){
    ProductBean productBean = new ProductBean();
    productBean.setProTitle(xxxx);
    productBean.setProInfo(xxxx);
    lists.add(productBean);
    }   
try {
      MyApplication.getDaoSession(MainActivity.this).runInTx(new Runnable() {
      @Override
      public void run() {
      for(ProductBean bean : lists){  
         MyApplication.getDaoSession(MainActivity.this).insertOrReplace(bean);                                    
        }
     }
   });
 }catch (Exception e){
         e.printStackTrace();
 }

2. 删除(删之前要先查一下,删除的方法有很多,可以删单条数据,也可以全部删除等等)

ProductBean bean = dao.queryBuilder().where(ProductBeanDao.Properties.ProTitle.eq("中青年抗癌互助计划")).build().unique();
                    if(bean != null){
                        dao.delete(bean);
                    }

3. 修改

ProductBean bean = dao.queryBuilder().where(ProductBeanDao.Properties.ProTitle.eq("中青年抗癌互助计划")).build().unique();
if(bean != null){
      bean.setProTitle("修改title");
      dao.update(bean);
     }

4. 查询(可以写多个查询条件where,可以设置升序(orderAsc)、降序排列,limit:限制用于显示查询数据的数量,这里只要求显示3条数据,list():表示查询结果为一个集合, 当然了,还可以查单条数据unique())

List<ProductBean> lists = dao.queryBuilder()
                            .where(ProductBeanDao.Properties.ProId.eq(3))
                            .where(.......)
                            .orderAsc(ProductBeanDao.Properties.ProId)
                            .limit(3)
                            .build().list();

最后看下MainActivity的全部代码(这里我没有采用id自增长的方式(不然数据会添加重复数据),而是用返回数据中的id作为主键,并且采用dao.insertOrReplace(productBean)的方式防止重复添加,不能使用dao.insert(),因为主键不可重复,这样当再次点击按钮添加重复的数据就会报错。仅是测试,情景不同,具体情况具体对待)

public class MainActivity extends AppCompatActivity {

    private ListView listView;
    private ProductAdapter adapter;
    private List<ListProBean> lists;
    private Button btnRequest;
    private static final  String url = "http://test.xinlechou.com/index.php?r=api/insuranceList";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化控件
        iniViews();
        getRequestDatas();
    }

    private void iniViews() {
        listView = (ListView) findViewById(R.id.listView);
        btnRequest = (Button) findViewById(R.id.btn_request);
    }

    public void getRequestDatas() {
        btnRequest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //数据库,获取DAO
                final ProductBeanDao dao = MyApplication.getDaoSession(MainActivity.this).getProductBeanDao();
                if(NetUtil.isNetConnected(MainActivity.this)){
                    //volley请求数据
                    StringRequest request = new StringRequest(url, new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            Gson gson = new Gson();
                            ListProBean bean = gson.fromJson(response,ListProBean.class);
                            if(bean.getError() == 0){
                                ArrayList<ProductData> datas = bean.getData();
                                adapter = new ProductAdapter(MainActivity.this,datas);
                                listView.setAdapter(adapter);
                                //将数据保存到greendao数据库
                                for(int i=0;i<datas.size();i++){
                                    ProductData productData = datas.get(i);
                                    ProductBean productBean = new ProductBean(null,null,productData.getName(),productData.getInfo(),Long.parseLong(productData.getId()));
                                    //插入数据库
                                   // boolean flag = dao.insert(productBean) != -1 ? true : false;
                                    boolean flag = dao.insertOrReplace(productBean) != -1 ? true : false;
                                    if(flag){
                                        Log.i("TAG","插入成功:"+i);
                                    }else{
                                        Log.i("TAG","插入失败:"+i);
                                    }
                                }
                            }
                        }
                    }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            //打印错误信息
                        }
                    });
                    //将请求放到队列中
                    MyApplication.getApplication().requestQueue.add(request);
                }else{
                    Toast.makeText(MainActivity.this,"没有联网哟",Toast.LENGTH_SHORT).show();
                    //查数据库
                    List<ProductBean> lists = dao.queryBuilder().build().list();
                    if(lists != null && lists.size() > 0){
                        Toast.makeText(MainActivity.this,"从数据库中读取数据",Toast.LENGTH_SHORT).show();
                        List<ProductData> productDatas = new ArrayList<ProductData>();
                        for(int i=0;i<lists.size();i++){
                            ProductBean productBean = lists.get(i);
                            String title = productBean.getProTitle();
                            String info = productBean.getProInfo();
                            ProductData productData = new ProductData();
                            productData.setName(title);
                            productData.setInfo(info);
                            productDatas.add(productData);
                        }
                        adapter = new ProductAdapter(MainActivity.this,productDatas);
                        listView.setAdapter(adapter);
                    }
                }
            }
        });
    }
}

当然了,这里主要介绍了GreenDao3.X 的一些基本使用,还有一些更加深入的知识点,比如:表与表之间的一对一、一对多等映射关系,以及我们要进行数据库升级等操作,我们要自定义OpenHelper继承DaoMaster.DevOpenHelper重写onUpgrade()方法,不然数据库在更新的时候就会新建表,原数据就会丢失。对于这些知识点目前没有深究,以后用到了,我再加以补充,希望能对大家有所帮助,如果发现讲述的有问题,欢迎指出

源码地址:点击下载源码

最后给出查看数据库的一个工具下载地址:http://www.sqliteexpert.com/

猜你喜欢

转载自blog.csdn.net/xiaxiazaizai01/article/details/53118748