【Android - 框架】之GreenDao的使用


  上一篇博客(【Android - 框架】之ORMLite的使用)中介紹了ORMLite的基本使用,今天我們來研究以下GreenDao的使用。

  GreenDao和ORMLite一樣,都是基於ORM(Object Relation Mapping,對象關系映射)的用於操作Sqlite數據庫的第三方框架。ORM簡單來說就是把數據庫中的數據映射成Java中的一個Bean類,便於操作。GreenDao是greenrobot公司的產品。這個公司的另一個非常成功的框架是EventBus,是一個很好的“訂閱/發布”的事件處理框架。

  好了,閑話不說,下面來簡單介紹以下GreenDao這個框架。

 

1、GreenDao和ORMLite的比較

ORMLite:

優點:ORMLite最大的優點是簡單,容易上手。
缺點:ORMLite是基於反射機制工作的,而反射是非常耗時的,因此這便成為了ORMLite的一個缺點,也是GreenDao最針對ORMLite的一點。

GreenDao:

優點:效率很高。下面是GreenDao官網上的一張圖,將GreenDao的各方面與其他的框架做比較。從圖中可以非常清晰的看到,GreenDao在增、改、查方面都比其他框架快出一大截,尤其是查詢。這是因為,GreenDao本身底層使用的不是反射,而是有一個Java工程來專門生成必要的代碼。

缺點:GreenDao的缺點是學習成本高。這個框架不像ORMLite那樣簡單易上手,使用GreenDao之前需要配置一大堆參數,即它封裝的不是很完整。

從上面的比較來看,如果項目對數據庫操作的效率要求非常高,那么我們可以考慮使用GreenDao,否則,我們還是使用簡單易上手的ORMLite吧。

 

2、配置GreenDao

1、在主Module的build.gradle中配置GreenDao的一些參數,加入GreenDao的依賴以及SourceSets。具體代碼如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.example.itgungnir.testgreendao"
        minSdkVersion 11
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    // -------------------下面加入的代碼-----------------------
    sourceSets {
        main {
            java.srcDirs = ['src/main/java', 'src/main/java-gen']
        }
    }
    // -------------------上面加入的代碼-----------------------
}

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:24.2.1'
    testCompile 'junit:junit:4.12'
    // -------------------下面加入的代碼-----------------------
    compile 'org.greenrobot:greendao:3.2.0'
    // -------------------上面加入的代碼-----------------------
}

2、在同一個Project中創建一個JAVA項目,具體步驟如下:

(1)依次點擊 File -> New -> New Module ,選擇Java Library,點擊Next,如下圖:

(2)Library Name和Java Class Name隨意寫,我在這里寫的Library Name是generator,Class Name是MyGenerator。寫完后點擊Finish按鈕。

(3)在generator項目的build.gradle中添加GreenDao的Generator的依賴,代碼如下:

apply plugin: 'java'

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'org.greenrobot:greendao-generator:3.2.0'
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"

  關於GreenDao的更多配置信息的設置,大家可以到  這里  查看。

(4)在主項目中main文件夾下(與java文件夾同級)的地方新建一個文件夾,命名為java-gen,GreenDao中自動生成的Dao、DaoMaster、Session以及Bean都將放到這個文件夾中。

(5)在MyGenerator中編寫初始化數據庫的代碼,具體代碼如下,注釋完整清晰,這里就不再贅述了:

import org.greenrobot.greendao.generator.DaoGenerator;
import org.greenrobot.greendao.generator.Entity;
import org.greenrobot.greendao.generator.Property;
import org.greenrobot.greendao.generator.Schema;

public class MyGenerator {
    private static Entity user;
    private static Entity article;

    public static void main(String args[]) {
        try {
            // 第一個參數:數據庫版本號;第二個參數:將生成的實體類放到哪個包下
            Schema schema = new Schema(3, "bean");
            // 將生成的DaoMaster、DaoSession和Dao類放到哪個包下
            schema.setDefaultJavaPackageDao("dao");
            // 將單元測試文件放到哪個包下
            schema.setDefaultJavaPackageTest("test");
            // 初始化數據表
            initUserTable(schema);
            initArticleTable(schema);
            // 開始自動生成代碼
            new DaoGenerator().generateAll(schema, "app/src/main/java-gen");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void initUserTable(Schema schema) {
        user = schema.addEntity("UserBean"); // 表名
        user.setTableName("user"); // 可以對表重命名
        user.addIdProperty().autoincrement();// 添加主鍵字段
        user.addStringProperty("name"); // 添加一個字符串類型的字段,名為name
        user.addBooleanProperty("gender"); // 添加一個布爾類型的字段,名為gender
        user.addIntProperty("age"); // 添加一個整形字段,名為age
    }

    private static void initArticleTable(Schema schema) {
        article = schema.addEntity("ArticleBean");
        article.setTableName("article");
        article.addIdProperty().autoincrement();
        article.addStringProperty("title");
        // 添加外鍵user_id,與user表關聯,指向user表的主鍵字段
        Property user_id = article.addLongProperty("user_id").getProperty();
        article.addToOne(user, user_id);
    }
}

  這張表中有一個外鍵,即Article表中有一個User表的id的外鍵依賴。想知道更多關於外鍵的問題,大家可以去  這里  查看。

  另外需要注意的是,如果想要對數據表或其中信息進行修改,除了需要添加字段、減少字段、添加表或刪除表之外,還需要修改Schema對象中的版本號。比如我對這個數據庫做了兩次修改,因此當前的數據庫版本號是3。

(6)編輯完MyGenerator類之后,我們需要運行這個類。選擇這個類之后右鍵選擇 Run XXX.main() ,如下圖所示:

        如果運行正常,則會在java-gen文件夾下生成一些類,如下圖所示:

 

(7)如果順利完成了以上步驟,那么下一步我們就要開始寫具體的操作數據庫的代碼了。

 

3、寫代碼操作數據庫

  我們想要完成這樣一個需求:對用戶表中的數據進行查詢,顯示到界面中的ListView中,在右上角有一個 添加 按鈕,當我們點擊這個按鈕的時候會向數據庫中添加一條數據;當我們長按ListView中的某一項時,會從數據庫中刪除這條數據。

  下面是具體的代碼。

1、數據庫管理類:

  我們可以直接使用GreenDao為我們自動生成的DaoMaster.OpenHelper,但最推薦的方法是我們用一個類來繼承這個類,這樣在數據庫版本變更的時候就可以對數據庫進行一些改進。我們定義一個MyDatabaseHelper,代碼如下:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import dao.DaoMaster;

/**
 * 封裝的數據庫管理類
 */
public class MyDatabaseHelper extends DaoMaster.OpenHelper {

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

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
            case 1:
                // 當數據庫更新時進行的操作
                break;
        }
    }
}

2、自定義Dao類:

  雖然GreenDao給我們自動生成了一個UserBeanDao類,但是我們有些需求是復合的,無法直接通過這個類中提供的方法進行操作,因此我們需要自己創建一個類來對數據等進行管理。定義一個MyDaoHelper類,其中封裝了這張表中常用的操作方法,代碼如下:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;

import com.example.itgungnir.testgreendao.SharedData;
import com.example.itgungnir.testgreendao.db.MyDatabaseHelper;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.query.QueryBuilder;

import java.util.List;

import bean.UserBean;
import dao.DaoMaster;
import dao.DaoSession;
import dao.UserBeanDao;

public class MyDaoHelper {
    private static MyDaoHelper instance;
    private UserBeanDao dao;

    private MyDaoHelper(Context context) {
        try {
            MyDatabaseHelper helper = new MyDatabaseHelper(context, SharedData.DATABASE_NAME, null);
            SQLiteDatabase db = helper.getWritableDatabase();
            DaoMaster daoMaster = new DaoMaster(db);
            DaoSession session = daoMaster.newSession();
            dao = session.getUserBeanDao();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static MyDaoHelper getInstance(Context context) {
        if (instance == null) {
            instance = new MyDaoHelper(context);
        }
        return instance;
    }

    public void addData(UserBean bean) {
        if (dao != null && bean != null) {
            dao.insertOrReplace(bean);
        }
    }

    public void deleteData(long id) {
        if (dao != null && !TextUtils.isEmpty(id + "")) {
            dao.deleteByKey(id);
        }
    }

    public UserBean getDataById(long id) {
        if (dao != null && !TextUtils.isEmpty(id + "")) {
            return dao.load(id);
        }
        return null;
    }

    public List<UserBean> getAllData() {
        if (dao != null) {
            return dao.loadAll();
        }
        return null;
    }

    public long getTotalCount() {
        if (dao == null) {
            return 0;
        }
        QueryBuilder<UserBean> qb = dao.queryBuilder();
        return qb.buildCount().count();
    }

    public void deleteAll() {
        if (dao != null) {
            dao.deleteAll();
        }
    }
}

3、MainActivity中的代碼如下:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;

import com.example.itgungnir.testgreendao.adapter.UserAdapter;
import com.example.itgungnir.testgreendao.dao.MyDaoHelper;

import java.util.List;

import bean.UserBean;
import dao.UserBeanDao;

public class MainActivity extends AppCompatActivity {
    private Button add;
    private ListView lv;

    private MyDaoHelper userDao;

    private List userList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化控件
        add = (Button) findViewById(R.id.id_main_btn_add);
        lv = (ListView) findViewById(R.id.id_main_lv_lv);
    }

    @Override
    protected void onResume() {
        super.onResume();
        initBDTables();
        initViews();
        initEvents();
    }

    private void initBDTables() {
        // 初始化兩個Dao類
        userDao = MyDaoHelper.getInstance(MainActivity.this);
        // 刪除數據表中的所有數據
        userDao.deleteAll();
        // 向用戶表中添加數據
        userDao.addData(new UserBean(1L, "張三", true, 20));
        userDao.addData(new UserBean(2L, "李四", false, 21));
        userDao.addData(new UserBean(3L, "王五", true, 22));
    }

    private void initViews() {
        // 從數據庫中取出所有用戶信息
        userList = userDao.getAllData();
        // 適配ListView數據
        UserAdapter adapter = new UserAdapter(MainActivity.this, userList);
        lv.setAdapter(adapter);
    }

    private void initEvents() {
        // 點擊add按鈕(添加)時觸發的事件
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 添加一條數據
                userDao.addData(new UserBean(((UserBean) userList.get(userList.size() - 1)).getId() + 1, "新用戶",
                        ((int) (Math.random() * 1000 + 1)) % 2 == 0 ? true : false, (int) (Math.random() * 20 + 20)));
                initViews();
            }
        });
        // 當長按ListView中的某一項時觸發的事件
        lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                // 刪除長按的Item
                userDao.deleteData(((UserBean) userList.get(position)).getId());
                initViews();
                return true;
            }
        });
    }
}

  這里追加一個ListView的適配器類UserAdapter類中的代碼:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.example.itgungnir.testgreendao.R;

import java.util.List;

import bean.UserBean;

/**
 * MainActivity中展示用戶信息的ListView的適配器
 */
public class UserAdapter extends BaseAdapter {
    private List list;
    private LayoutInflater inflater;

    public UserAdapter(Context context, List list) {
        this.list = list;
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.listitem_users, parent, false);
            holder.name = (TextView) convertView.findViewById(R.id.id_useritem_name);
            holder.gender = (TextView) convertView.findViewById(R.id.id_useritem_gender);
            holder.age = (TextView) convertView.findViewById(R.id.id_useritem_age);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        UserBean user = (UserBean) getItem(position);
        holder.name.setText(user.getName());
        holder.gender.setText(user.getGender() == true ? "男" : "女");
        holder.age.setText(user.getAge() + "");
        return convertView;
    }

    private static class ViewHolder {
        TextView name;
        TextView gender;
        TextView age;
    }
}

5、運行結果如下圖所示:

 

  以上就是對GreenDao框架的簡單介紹,希望對大家有幫助~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM