greendao 3.0整合和使用封裝
現在專案中要用到資料庫,最終選擇使用了greendao ,至於原因,肯定是效能原因了。本文將著重介紹資料庫的非同步操作,因為網上很多都是配置整合+簡單的使用,並且都還是同步的(重要的是 都是一樣的文章!!!)。我想說,如果是百萬級的資料就GG了。
一般來說,我們需要資料時,先訪問資料庫看是否有資料,如果有,就從資料庫取,如果沒有,就訪問網路,成功後,將開啟執行緒將資料插入資料庫中,同事更新UI 如下圖所示:
1:整合配置
apply plugin: 'org.greenrobot.greendao'
greendao {
schemaVersion 1
daoPackage 'com.app.test.textgreendao.db' //這個填寫你自己建立的路徑
targetGenDir 'src/main/java'
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.0.0'
}
}
dependencies {
compile'org.greenrobot:greendao:3.0.1'
compile'org.greenrobot:greendao-generator:3.0.0'
}
2:接下來就是建立實體類了:
/**
* Created by ${liumengqiang} on 2017/7/10.
*/
@Entity
public class User {
@Id
private long memberId;
@Property
private String name;
@Property
private String age;
}
然後點選 Build —— make build 就是那個綠色小錘子按鈕,就會自動幫你生成相應的方法;
至於@Id,@Property 這一類的標記 大家可以上網搜一下 這個不再贅述。
3:然後就是自己封裝GreenDao了,首先網上很多都是同步資料 在這裡 我用的是非同步處理的也就是使用的是AsyncSession類,這個是GreenDao內部封裝好的 再次我們可以在封裝一下,專門用於非同步操作資料庫的成功和失敗;
首先 我定義了返回操作資料庫結果的回撥介面
package com.app.test.textgreendao.user;
import java.util.List;
/**
* Created by ${liumengqiang} on 2017/7/12.
*/
public interface UserInterface {
/**
* type true 成功。 false 失敗
* @param <T>
*/
interface OnIsertInterface<T>{//單個插入成功
void onIsertInterface(boolean type);
}
interface OnQuerySingleInterface<T>{//單個查詢成功
void onQuerySingleInterface(T entry);
}
interface OnDeleteInterface<T>{//單個刪除成功
void onDeleteInterface(boolean type);
}
interface OnUpdateInterface<T>{//單個修改成功
void onUpdateInterface(boolean type);
}
interface OnQueryAllInterface<T>{//批量查詢資料回撥
void onQueryAllBatchInterface(List<T> list);
}
}
然後 我們宣告這些介面:
package com.app.test.textgreendao.db;
import com.app.test.textgreendao.user.UserInterface;
/**
* Created by ${liumengqiang} on 2017/7/12.
*/
public class DaoInterface<T> {
protected UserInterface.OnQueryAllInterface<T> onQueryAllInterface;
protected UserInterface.OnUpdateInterface<T> onUpdateInterface;
protected UserInterface.OnIsertInterface<T> onIsertInterface;
protected UserInterface.OnQuerySingleInterface<T> onQuerySingleInterface;
protected UserInterface.OnDeleteInterface<T> onDeleteInterface;
public UserInterface.OnQueryAllInterface<T> getOnQueryAllInterface() {
return onQueryAllInterface;
}
public void setOnQueryAllInterface(UserInterface.OnQueryAllInterface<T> onQueryAllInterface) {
this.onQueryAllInterface = onQueryAllInterface;
}
public UserInterface.OnUpdateInterface<T> getOnUpdateInterface() {
return onUpdateInterface;
}
public void setOnUpdateInterface(UserInterface.OnUpdateInterface<T> onUpdateInterface) {
this.onUpdateInterface = onUpdateInterface;
}
public UserInterface.OnIsertInterface<T> getOnIsertInterface() {
return onIsertInterface;
}
public void setOnIsertInterface(UserInterface.OnIsertInterface<T> onIsertInterface) {
this.onIsertInterface = onIsertInterface;
}
public UserInterface.OnQuerySingleInterface<T> getOnQuerySingleInterface() {
return onQuerySingleInterface;
}
public void setOnQuerySingleInterface(UserInterface.OnQuerySingleInterface<T> onQuerySingleInterface) {
this.onQuerySingleInterface = onQuerySingleInterface;
}
public UserInterface.OnDeleteInterface<T> getOnDeleteInterface() {
return onDeleteInterface;
}
public void setOnDeleteInterface(UserInterface.OnDeleteInterface<T> onDeleteInterface) {
this.onDeleteInterface = onDeleteInterface;
}
}
首先封裝一下資料庫 DaoManager ,這個網上很多 ,直接看下程式碼吧
package com.app.test.textgreendao.db;
import android.content.Context;
/**
* Created by ${liumengqiang} on 2017/7/10.
*/
public class DaoManager {
private static DaoManager daoManager;
private DaoMaster daoMaster;
private DaoSession daoSession = null;
private DaoMaster.DevOpenHelper devOpenHelper;
private DaoManager(){};
public static DaoManager getInstance(){
if(daoManager == null){
daoManager = new DaoManager();
}
return daoManager;
}
public DaoMaster getDaoManager(Context context, String DB_NAME){
if(daoMaster == null){
devOpenHelper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
}
return daoMaster;
}
public DaoSession getDaoSession(){
if(daoSession == null){
daoSession = daoMaster.newSession();
}
return daoSession;
}
/**
* 關閉DaoSession
*/
private void closeDaoSession(){
if(daoSession != null){
daoSession.clear();
daoSession = null;
}
}
/**
* 關閉Helper
*/
private void closeHelper(){
if(devOpenHelper != null){
devOpenHelper.close();
devOpenHelper = null;
}
}
/**
* 關閉所有的操作
*/
public void closeConnection(){
closeDaoSession();
closeHelper();
}
}
然後就是我們核心部分了,就是處理建立一個類DaoUtils繼承UserInterface類,
daoSession.startAsyncSession()返回一個AsyncSession物件,通過該物件我們可以通過setListenerMainThread 方法監聽操作資料庫的結果, 然後在執行增刪改查,比如:asyncSession.queryUnique(query);
package com.app.test.textgreendao.db;
import android.content.Context;
import org.greenrobot.greendao.async.AsyncOperation;
import org.greenrobot.greendao.async.AsyncOperationListener;
import org.greenrobot.greendao.async.AsyncSession;
import org.greenrobot.greendao.query.DeleteQuery;
import org.greenrobot.greendao.query.Query;
import org.greenrobot.greendao.query.WhereCondition;
import java.util.List;
/**
* Created by ${liumengqiang} on 2017/7/11.
*/
public class DaoUtils<T> extends DaoInterface{
private DaoManager daoManager;
public DaoSession daoSession;
public DaoUtils(Context context, String dao_name){
daoManager = DaoManager.getInstance();
daoManager.getDaoManager(context, dao_name);
daoSession = daoManager.getDaoSession();
}
/**
* 條件查詢資料
* @param cls
* @return
*/
public <T>void query(Class cls, WhereCondition whereCondition){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onQuerySingleInterface != null){
onQuerySingleInterface.onQuerySingleInterface(operation.getResult());
}else if(onQuerySingleInterface != null){
onQuerySingleInterface.onQuerySingleInterface(null);
}
}
});
Query query = daoSession.queryBuilder(cls).where(whereCondition).build();
asyncSession.queryUnique(query);
}
public T query(Class cls, String whereString, String[] params){
return (T) daoSession.getDao(cls).queryRaw(whereString, params);
}
/**
* 批量查詢
* @param object
* @return
*/
public void queryAll(Class object, Query<T> query){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
List<T> result = (List<T>)operation.getResult();
onQueryAllInterface.onQueryAllBatchInterface(result);
}
});
if(query == null){
asyncSession.loadAll(object);
}else{
asyncSession.queryList(query);
}
// return objects;
}
/**
* 刪除
*/
public void deleteSingle(T entry){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onDeleteInterface != null){
onDeleteInterface.onDeleteInterface(true);
}else if(onDeleteInterface != null){
onDeleteInterface.onDeleteInterface(false);
}
}
});
asyncSession.delete(entry);
}
/**
* 批量刪除
*/
public void deleteBatch(Class cls,final List<T> list){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onDeleteInterface != null){
onDeleteInterface.onDeleteInterface(true);
}else if(onDeleteInterface != null){
onDeleteInterface.onDeleteInterface(false);
}
}
});
asyncSession.deleteInTx(cls, list);
}
/**
* 根據Id單個刪除
*/
public void deleteByIdSingle(Class cls,long longParams){//此處longParams數值型別必須為主鍵id的型別
daoSession.getDao(cls).deleteByKey(longParams);
}
/**
* 根據Id批量刪除
*/
public void deleteByIdBatch(Class cls, List<Long> longList){//同上
daoSession.getDao(cls).deleteByKeyInTx(longList);
}
/**
* 刪除所有資料
*/
public void deleteAll(Class cls){
final AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onDeleteInterface != null){
onDeleteInterface.onDeleteInterface(true);
}else if(onDeleteInterface != null){
onDeleteInterface.onDeleteInterface(false);
}
}
});
asyncSession.deleteAll(cls);
}
/**
* 插入一條資料
*/
public void insertSingle(final T entity){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onIsertInterface != null){
onIsertInterface.onIsertInterface(true);
}else if(onIsertInterface != null){
onIsertInterface.onIsertInterface(false);
}
}
});
asyncSession.runInTx(new Runnable() {
@Override
public void run() {
daoSession.insert(entity);
}
});
}
/**
* 批量插入
*/
public <T>void insertBatch(final Class cls,final List<T> userList){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onIsertInterface != null){
onIsertInterface.onIsertInterface(true);
}else if(onIsertInterface != null){
onIsertInterface.onIsertInterface(false);
}
}
});
asyncSession.runInTx(new Runnable() {
@Override
public void run() {
for (T object : userList) {
daoSession.insertOrReplace(object);
}
}
});
}
/**
* 更新一個數據
*/
public <T>void updateSingle(Class cls,T entry){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onUpdateInterface != null){
onUpdateInterface.onUpdateInterface(true);
}else if(onUpdateInterface != null){
onUpdateInterface.onUpdateInterface(false);
}
}
});
asyncSession.update(entry);
}
/**
* 批量更新資料
*/
public <T>void updateBatch(final Class cls, final List<T> tList){
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully() && onUpdateInterface != null){
onUpdateInterface.onUpdateInterface(true);
}else if(onUpdateInterface != null){
onUpdateInterface.onUpdateInterface(false);
}
}
});
asyncSession.updateInTx(cls, tList);
}
}
上面的核心類,有幾個我搞的不太懂 就是那個根據id刪除的,如何整成非同步的;再有就是刪除非同步裡面的迭代器我不太會用。小夥伴們知道的話 可以交流溝通一下。
由於greendao是通過類的不同來識別的,所以當我們操作不同表時,都建立一個相應的操作資料庫Utils 繼承自DaoUtils。比如我建立的User類 就可以建立一個相應的操作資料庫utils類如下:
package com.app.test.textgreendao.user;
import android.content.Context;
import com.app.test.textgreendao.db.DaoUtils;
import com.app.test.textgreendao.db.UserDao;
import org.greenrobot.greendao.async.AsyncOperation;
import org.greenrobot.greendao.async.AsyncOperationListener;
import org.greenrobot.greendao.async.AsyncSession;
import org.greenrobot.greendao.query.Query;
import java.util.ArrayList;
import java.util.List;
/**
* Created by ${liumengqiang} on 2017/7/11.
*/
public class UserDaoUtils extends DaoUtils<User>{
public UserDaoUtils(Context context, String dao_name) {
super(context, dao_name);
}
/**
* 單個插入
* @param user
*/
public void insertUser(User user){
insertSingle(user);
}
/**
* 批量插入
*/
public void insertBatchUser(List<User> list){
insertBatch(User.class,list);
}
/**
* 條件查詢
*/
public void queryWhereUser(long memberId){
query(User.class, UserDao.Properties.MemberId.eq(memberId));
}
/**
* 查詢全部
*/
public void queryAllUser(){
queryAll(User.class, null);
// return users;
}
/**
* 條件刪除
*/
public void deleteSingleUser(long memberId){
User user = new User();
user.setMemberId(memberId);
deleteSingle(user);
}
/**
* 批量刪除
*/
public void deleteBatchUser(List<Integer> integerList){
List<User> userList = new ArrayList<>();
for(int i = 0;i < integerList.size(); i++){
User user = new User();
user.setMemberId(integerList.get(i));
userList.add(user);
}
deleteBatch(User.class, userList);
}
/**
* 單個更新
*/
public void updateSingleUser(User user){
updateSingle(User.class, user);
}
/**
* 批量更新
*/
public void updateBatchUser(List<User> list){
updateBatch(User.class,list);
}
/**
* 根據Id 單個刪除
*/
public void deleteByIdSingleUser(long memberId){
deleteByIdSingle(User.class, memberId);
}
/**
* 根據Id批量刪除
*/
public void deleteByIdBatchUser(List<Long> longList){
deleteByIdBatch(User.class, longList);
}
/**
* 刪除所有
*/
public void deleteAll(){
deleteAll(User.class);
}
/**
* 條件批量刪除
*/
public void deleteWhereBatch(String ageString){
Query<User> build = daoSession.queryBuilder(User.class).where(UserDao.Properties.Age.eq(ageString)).build();
AsyncSession asyncSession = daoSession.startAsyncSession();
asyncSession.setListenerMainThread(new AsyncOperationListener() {
@Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
if(operation.isCompletedSucessfully()){
deleteBatch(User.class, (List<User> )operation.getResult());
}
}
});
asyncSession.queryList(build);
}
}
當我們需要在view層操作資料庫的結果時,比如插入結果,我們可以通過:
userDaoUtils = new UserDaoUtils(getApplicationContext(), "123456789");
userDaoUtils.setOnIsertInterface(new UserInterface.OnIsertInterface() {
@Override
public void onIsertInterface(boolean type) {
if(type){
/**
* 插入一條資料成功
*/
}
}
});
這樣是不是方便多了。
其次有幾個坑大家共勉:
1: 刪除資料時, greendao是根據Id進行刪除的。
2:新增或刪除欄位時,需要刪除重新安裝apk
3: 建立的實體類 ,不要建立成內部類。