Android APK开发基础——数据存储安卓数据库之GreenDao

一、举个例子

1、开发

1、配置

工程配置文件中添加: 

buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0

        //greendao配置
        classpath 'org.greenrobot:greendao-gradle-plugin:3.0.0'

    }
}
 

module配置文件中添加:
apply plugin: 'com.android.application'
apply plugin: 'com.antfortune.freeline'
apply plugin: 'org.greenrobot.greendao'

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.2'
    defaultConfig {
        applicationId "com.zxcn.test"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    //android里添加下面代码
    greendao {
        schemaVersion 1
        daoPackage 'com.hy.AndroidBase.gen'  //一般为app包名+生成文件的文件夹名
        targetGenDir 'src/main/java'   //生成文件路径;这个目录必须这样写,否则自动编译的会出错
    }

}

repositories {
    // ...
    maven { url "https://jitpack.io" }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'io.reactivex:rxjava:1.1.5'
    compile project(':mylib')

    compile'org.greenrobot:greendao:3.0.1'
    compile'org.greenrobot:greendao-generator:3.0.0'

}

2、创建实体类User

package com.hy.base.androidbase.androidbasesave.greendao;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Generated;

@Entity
public class User {
    @Id
    private Long id;
    private String name;
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @Generated(hash = 873297011)
    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }
    @Generated(hash = 586692638)
    public User() {
    }

    @Override
    public String toString(){
        return "UserInfo1{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

在AndroidStudio编译,自动生成:

 

3、在Application里配置数据库:

public class MyApplication extends Application {
    String tag = "060_MyApp";

    private static MyApplication sInstance;

    private MyActivityManager activityManager = null; // activity管理类

    //单例模式
    public static synchronized MyApplication getInstance() {
        return sInstance;
    }
    /**
     * 提供全局获取 Context
     */
    private static Context context;
    public static Context getContext() {
        return context;
    }

    /**
     * 重写Application生命周期
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(tag,"MyApplication onCreate");

        context = getApplicationContext();

        initCrashHandler();
        initGlobalManager();
        initGlobalService();
        initDatabase();

        //配置数据库
        setupGreenDaoDatabase();
    }
    @Override
    public void onTerminate() {
        // 程序终止的时候执行
        Log.e(tag, "onTerminate");
        super.onTerminate();
    }
    @Override
    public void onLowMemory() {
        // 低内存的时候执行
        Log.e(tag, "onLowMemory");
        super.onLowMemory();
    }
    @Override
    public void onTrimMemory(int level) {
        // 程序在内存清理的时候执行
        Log.e(tag, "onTrimMemory");
        super.onTrimMemory(level);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.e(tag, "onConfigurationChanged");
        super.onConfigurationChanged(newConfig);
    }

    public MyActivityManager getActivityManager() {
        return activityManager;
    }

    public void initCrashHandler() {

    }

    public void initGlobalManager() {
        // 获得activity管理类实例
        activityManager = MyActivityManager.getInstance();
    }

    public void initGlobalService() {
        //启动应用级的service
//        startService(new Intent(getApplicationContext(), MyService.class));
//        startService(new Intent(getApplicationContext(), MyForegroundService.class));
    }

    public void initDatabase() {
        DatabaseHelper.getHelper(getApplicationContext());
    }

    private void setupGreenDaoDatabase(){
        //创建数据库shop.db
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "shop.db", null);
        //获取可写数据库
        SQLiteDatabase db = helper.getWritableDatabase();
        //获取数据库对象
        DaoMaster daoMaster = new DaoMaster(db);
        //获取dao对象管理者
        daoSession = daoMaster.newSession();
    }

    private static DaoSession daoSession;
    public static DaoSession getDaoInstant() {
        return daoSession;
    }
}

4、创建增删改查的类

public class UserUtils {
    private static UserUtils mUserUtils;

    public UserUtils(){

    }

    public static UserUtils getUserUtils(){
        if (mUserUtils == null) {
            mUserUtils = new UserUtils();
        }
        return mUserUtils;
    }

    /**
     * 添加数据,如果有重复则覆盖
     *
     */
    public  void insert(User mUser) {
        MyApplication.getDaoInstant().getUserDao().insertOrReplace(mUser);
    }

    /**
     * 删除数据
     *
     * @param id
     */
    public  void delete(long id) {
        MyApplication.getDaoInstant().getUserDao().deleteByKey(id);
    }

    /**
     * 更新数据
     */
    public  void update(User mUser) {
        MyApplication.getDaoInstant().getUserDao().update(mUser);
    }

    /**
     * 查询Type为1的所有数据
     *
     * @return
     */
    public  List<User> queryUser(String name) {
        return MyApplication.getDaoInstant().getUserDao().queryBuilder().where(UserDao.Properties.Name.eq(name)).list();

    }

    /**
     * 查询所有数据
     *
     * @return
     */
    public  List<User> queryAll() {
        return MyApplication.getDaoInstant().getUserDao().loadAll();
    }
}

5、调用:

insertg.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        UserUtils.getUserUtils().insert(new User(1L,"zhangsan"));
        UserUtils.getUserUtils().insert(new User(2L,"lisi"));
        UserUtils.getUserUtils().insert(new User(1L,"wangwu"));
        UserUtils.getUserUtils().insert(new User(1L,"zhaoliu"));
    }
});
deleteg.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        UserUtils.getUserUtils().delete(1);
    }
});
updateg.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        UserUtils.getUserUtils().update(new User(2L,"hahahha"));
    }
});
queryg.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        UserUtils.getUserUtils().queryUser("zhaoliu");
    }
});
queryallg.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        List<User> all = UserUtils.getUserUtils().queryAll();
        for (int i = 0; i < all.size(); i++) {
            Log.e("060", "all[" + i + "] :" + all.get(i).toString());
        }
    }
});

6、采用RecyclerView显示。

(1)给实体User创建对应的Adapter类。

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {

    private LayoutInflater mInflater;
    private List<User> mDatas;

    public UserAdapter(Context context, List<User> mDataBean) {
        Log.e("060 DataBeanAdapter:","0");

        mInflater = LayoutInflater.from(context);
        mDatas = mDataBean;
    }

    /**
     * 创建ViewHolder,每个ViewHolder管理一个item。因为ViewHolder会重复利用,
     * 所以如果Recyclerview有12个item,可能只创建7个ViewHolder
     */
    int count_create = 0;
    int count_bind = 0;

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        count_create++;
        Log.e("060 onCreateViewHolder:",count_create + "");

        View view = mInflater.inflate(R.layout.item_user, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(view);
        viewHolder.mid = (TextView) view.findViewById(R.id.id);
        viewHolder.mname = (TextView) view.findViewById(R.id.name);
        viewHolder.mage = (TextView) view.findViewById(R.id.age);
        return viewHolder;
    }


    /**
     * 绑定ViewHolder到Recyclerview
     */
    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
        count_bind++;

        viewHolder.mid.setText(mDatas.get(i).getId()+"");
        viewHolder.mname.setText(mDatas.get(i).getName());
        viewHolder.mage.setText(mDatas.get(i).getAge());

        //设置点击事件对应的回调
        if (mOnItemClickLitener != null) {
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickLitener.onItemClick(viewHolder.itemView, i);
                }
            });
        }
    }

    /**
     * ************************* 定义ViewHolder ******************************
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View arg0) {
            super(arg0);
        }
        TextView mid;
        TextView mname;
        TextView mage;
    }

    /**
     * *************************  重写Recyclerview Adapter的接口 ******************************
     */
    @Override
    public int getItemCount() {
        int m = 0;
        if(mDatas!=null){
            m = mDatas.size();
        }
        return m;
    }

    /**
     * *************************  Recyclerview item对应点击事件******************************
     */

    /**
     * RecyclerView Item 的点击事件回调接口
     */
    public interface OnItemClickLitener {
        void onItemClick(View view, int position);
    }

    private OnItemClickLitener mOnItemClickLitener;

    public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
        this.mOnItemClickLitener = mOnItemClickLitener;
    }

    /**
     * RecyclerView Item 的滚动事件回调接口
     */
    public interface OnScrollListener {
        // 状态为0时:当前屏幕停止滚动;
        // 状态为1时:屏幕在滚动 且 用户仍在触碰或手指还在屏幕上;
        // 状态为2时:随用户的操作,屏幕上产生的惯性滑动;
        //        void onScrollStateChanged(RecyclerView recyclerView, int newState);
        void onScrolled(RecyclerView recyclerView, int dx, int dy);
    }

    private OnScrollListener mOnScrollListener;

    public void setOnScrollListener(OnScrollListener mOnScrollListener) {
        this.mOnScrollListener = mOnScrollListener;
    }

}

R.layout.item_user对应的资源文件放到layout目录:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:orientation="vertical">

    <LinearLayout
        android:id="@+id/layout1"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/id"
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:layout_marginTop="15dp"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="some info"
            android:textSize="15sp"/>

        <TextView
            android:id="@+id/name"
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:layout_marginTop="15dp"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="some info"
            android:textSize="15sp"/>

        <TextView
            android:id="@+id/age"
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:layout_marginTop="15dp"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="some info"
            android:textSize="15sp"/>
    </LinearLayout>
    
    <View
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:layout_below="@+id/layout1"
        android:background="#e1f1f9"/>
</RelativeLayout>

(2)创建RecyclerView所位于的Activity类。

public class GreenDaoQureyActivity extends Activity {
    String tag = "060_GreenDaoQureyActivity";
    List<User> mDatas;
    UserAdapter mAdapter;
    RecyclerView mbphistory;

    Button bt1;
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gdquery);

        mbphistory = findViewById(R.id.mbphistory);

        bt1 = findViewById(R.id.bt1);
        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                queryall();
            }
        });
    }

    private void queryall() {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
        fixedThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    Log.e(tag,"time1 : "+ DateUtils.getDateStr(System.currentTimeMillis()));
                    for(long i= 0; i<1000;i++){
                        UserUtils.getUserUtils().insert(new User(i,"aa","20",""));
                    }
                    Log.e(tag,"time2 : "+ DateUtils.getDateStr(System.currentTimeMillis()));
                    mDatas = UserUtils.getUserUtils().queryAll();
                    Log.e(tag,"time3 : "+ DateUtils.getDateStr(System.currentTimeMillis()));

                    handler.sendEmptyMessage(0);

                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }

    private void overrideCallback() {
        mAdapter.setOnItemClickLitener(new UserAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(GreenDaoQureyActivity.this, position + "", Toast.LENGTH_SHORT).show();
                switch (position) {
                    case 0:
                        break;
                    default:
                }
            }
        });
    }


    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0:
                    mbphistory.setLayoutManager(new LinearLayoutManager(GreenDaoQureyActivity.this, LinearLayoutManager.VERTICAL, false));
                    mAdapter = new UserAdapter(GreenDaoQureyActivity.this, mDatas);
                    mbphistory.setAdapter(mAdapter);
                    //override click callback
                    overrideCallback();
                    break;
                case 2:

                    break;
            }
        }
    };

}

其对应的layout文件夹:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <Button
        android:id="@+id/bt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="query all"/>

    <LinearLayout
        android:layout_below="@+id/bt1"
        android:id="@+id/layout1"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:layout_marginTop="15dp"
            android:layout_weight="1"
            android:text="序号"
            android:gravity="center_horizontal"
            android:textSize="20sp"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:layout_marginTop="15dp"
            android:layout_weight="1"
            android:text="姓名"
            android:gravity="center_horizontal"
            android:textSize="20sp"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:layout_marginTop="15dp"
            android:layout_weight="1"
            android:text="年龄"
            android:gravity="center_horizontal"
            android:textSize="20sp"/>
    </LinearLayout>

    <View
        android:id="@+id/l1"
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:layout_below="@+id/layout1"
        android:background="#e1f1f9"/>

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_below="@+id/l1"
                    android:orientation="vertical">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/mbphistory"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:scrollbars="none"/>

    </RelativeLayout>

</RelativeLayout>

2、安卓mainthread数据库操作

数据库的操作很重,一次读写操作花费 10~20ms 是很常见的,这样的耗时很容易造成界面的卡顿。所以通常情况下,如果可以的话一定要避免在主线程中处理数据库。

方案:开线程方位数据库。

 

3、调试

1、数据库直观查看:

采用Facebook Stetho工具查看。

参考:
Android调式工具 --Facebook Stetho --无需root手机设备即可查看data目录下数据

https://blog.csdn.net/x767914233/article/details/70233471

 

2、APK应用显示查看:

采用RecyclerView显示。

 

bug1: RecyclerView显示为空。
https://blog.csdn.net/the_spring/article/details/54236996

 

二、数据库加密

工具:

SQLCipher

查看:

 Android 数据库 greenDao 3(包括加密) 封装使用 https://www.jianshu.com/p/427e0e9f396a

 

2、调试

使用SQLCipher加密数据库后,使用 Facebook Stetho数据库查看工具,确实不能查看数据库的内部数据了,说明加密起作用了。

 

三、数据库升级

目的:

不删除原有表,在表上增加字段 ,且保持原来字段的数据不被改变。

 

参考:

greendao3.0以上使用步骤(二):数据库到底该怎么升级

https://blog.csdn.net/huangxiaoguo1/article/details/54574713

 

数据库升级代码:

升级前效果

升级后效果

 

代码:

1、首先我们引入MigrationHelper类,内容如下:

package com.hy.base.androidbase.androidbasesave.greendao;

import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;

import com.hy.AndroidBase.gen.DaoMaster;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.internal.DaoConfig;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MigrationHelper {
    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
    private static MigrationHelper instance;

    public static MigrationHelper getInstance() {
        if (instance == null) {
            instance = new MigrationHelper();
        }
        return instance;
    }

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {

        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
    }

    /**
     * 生成临时列表
     *
     * @param db
     * @param daoClasses
     */
    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }

                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

                    if (daoConfig.properties[j].primaryKey) {
                        createTableStringBuilder.append(" PRIMARY KEY");
                    }

                    divider = ",";
                }
            }
            createTableStringBuilder.append(");");

            db.execSQL(createTableStringBuilder.toString());

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tableName).append(";");

            db.execSQL(insertTableStringBuilder.toString());

        }
    }

    /**
     * 存储新的数据库表 以及数据
     *
     * @param db
     * @param daoClasses
     */
    private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList();

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tempTableName).contains(columnName)) {
                    properties.add(columnName);
                }
            }

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();
            dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
            db.execSQL(insertTableStringBuilder.toString());
            db.execSQL(dropTableStringBuilder.toString());
        }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)) {
            return "TEXT";
        }
        if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
            return "INTEGER";
        }
        if (type.equals(Boolean.class)) {
            return "BOOLEAN";
        }

        Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
        exception.printStackTrace();
        throw exception;
    }

    private List<String> getColumns(Database db, String tableName) {
        List<String> columns = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
            if (cursor != null) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return columns;
    }
}

2、重写DaoMaster.OpenHelper的onUpgrade()方法。

创建MyOpenHelper:

public class MyOpenHelper extends DaoMaster.OpenHelper {

    public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    /**
     * 数据库升级
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        //操作数据库的更新 有几个表升级都可以传入到下面
        MigrationHelper.getInstance().migrate(db, UserDao.class);
    }
}

3、初始化DaoMaster时,注意引进MyOpenHelper。

/**
 * 初始化不加密的数据库
 */
private void setupGreenDaoDatabase() {
    //有数据库升级前,初始化DaoMaster
    if (null == daoMaster) {
        synchronized (GreenDaoApplication.class) {
            if (null == daoMaster) {
                MyOpenHelper helper = new MyOpenHelper(this, "user.db", null);
                daoMaster = new DaoMaster(helper.getWritableDatabase());
            }
        }
    }

    //获取dao对象管理者
    daoSession = daoMaster.newSession();
}

5、修改module gradle的greendao配置:

schemaVersion 加1

//android里添加下面代码
greendao {
    schemaVersion 2
    daoPackage 'com.hy.AndroidBase.gen'  //一般为app包名+生成文件的文件夹名
    targetGenDir 'src/main/java'   //生成文件路径;这个目录必须这样写,否则自动编译的会出错
}

四、特点

开发的角度

优点:

1、使用简单,无需从头开始写数据库。普通需求基本直用重写两个类,一个是数据bean类,一个是数据库操作类。

 

性能的角度

优点:

 

 

 

GitHub demo源码地址:

https://github.com/yuanhhyuan/AndroidDataSave

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值