快速入门GreenDao框架并实现增删改查案例
TimothyFuen
8年前
<p>大家的项目中不可避免的使用到SQLite,为此我们要花费心思编写一个增删改查框架。而一个好的ORM框架则能够给我们带来极大的方便,今天给大家讲解一个非常火热的ORM-GreenDao。</p> <h2>基本概念</h2> <p>GreenDao官网地址:<a href="/misc/goto?guid=4959673067565349529">http://greenrobot.org/greendao/</a></p> <h3>官网对GreenDao的介绍:</h3> <p> greenDAO is an open source library for Android providing an easy-to-use interface to SQLite to help developers handle data efficiently – relieving developers from dealing with low-level database stuff and saving development time. SQLite is an awesome embedded relational database. Still, writing SQL and parsing query results are quite tedious and time-consuming tasks. greenDAO frees you from these by mapping Java objects to database tables (often called ORM). This way you can store, update, delete, and query for Java objects using a simple object oriented API.</p> <p>简单的说就是:greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。</p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/524566dd282e06d78d8d58a8e27a352e.png"></p> <h3>greenDAO 设计的主要目标</h3> <ul> <li>一个精简的库</li> <li>性能最大化</li> <li>内存开销最小化</li> <li>易于使用的 APIs</li> <li>对 Android 进行高度优化</li> </ul> <h3>greenDAO 设计的主要特点</h3> <ul> <li>greenDAO 性能远远高于同类的 ORMLite,具体测试结果可见官网</li> <li>greenDAO 支持 protocol buffer(protobuf) 协议数据的直接存储,如果你通过 protobuf<br> 协议与服务器交互,将不需要任何的映射。</li> <li>与 ORMLite 等使用注解方式的 ORM 框架不同,greenDAO 使用「Code<br> generation」的方式,这也是其性能能大幅提升的原因。</li> </ul> <h3>Dao项目代码生成</h3> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/f9d9e2d337281ba006a6ce14e8dfce4e.png"></p> <h3>核心类介绍</h3> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/7a476a0789d1534425f81731407153f3.png"></p> <p><strong>DaoMaster:</strong>一看名字就知道它是Dao中的最大的官了。它保存了sqlitedatebase对象以及操作DAO classes(注意:不是对象)。其提供了一些创建和删除table的静态方法,其内部类OpenHelper和DevOpenHelper实现了SQLiteOpenHelper并创建数据库的框架。<br> <strong>DaoSession:</strong>会话层。操作具体的DAO对象(注意:是对象),比如各种getter方法。<br> <strong>XXXDao:</strong>实际生成的某某DAO类,通常对应具体的java类,比如NoteDao等。其有更多的权限和方法来操作数据库元素。<br> <strong>XXXEntity:</strong>持久的实体对象。通常代表了一个数据库row的标准java properties。</p> <p>了解了基本概念后我们开始动手完成一个增删改查的项目案例。</p> <h2>实现过程</h2> <h3>1.在 Android 工程中配置「greenDao Generator」模块</h3> <p>在 .src/main 目录下新建一个与 java 同层级的「java-gen」目录,用于存放由 greenDAO 生成的 Bean、DAO、DaoMaster、DaoSession 等类。</p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/88c73e5e0d1eafd145e6f3af8daf4aed.png"></p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/fb90d3e4c9589d66ab7b9ff5946a398c.png"></p> <p>配置 Android 工程(app)的 build.gradle,如图分别添加 sourceSets 与 dependencies</p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/9ff238531f72c578399ebc9455b3bfd9.png"></p> <pre> <code class="language-java">sourceSets { main { java.srcDirs = ['src/main/java', 'src/main/java-gen'] } }</code></pre> <pre> <code class="language-java">compile 'de.greenrobot:greendao:1.3.7'</code></pre> <h3>2.新建「greenDAO Generator」模块 (纯 Java 工程)</h3> <p>通过 File -> New -> New Module -> Java Library -> 填写相应的包名与类名 -> Finish</p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/55eb8070243671de07f5dc37e73bc583.png"></p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/fff11645aed142e622f89585e3640ac6.png"></p> <p>配置 castielgreendaolb 工程的 build.gradle,添加 dependencie</p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/e96b60787b07347feaa4ae00d9a079e9.png"></p> <p>注意主句话,配置输出路径</p> <pre> <code class="language-java">def outputDir = "../app/src/main/java-gen"</code></pre> <p>接着,编写 CastielGreenDao类,注意: 我们的 Java 工程只有一个类,它的内容决定了「GreenDao Generator」的输出,你可以在这个类中通过对象、关系等创建数据库结构,下面我将以注释的形式详细讲解代码内容。</p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/e97f5ba9a1865f6ba2d271613a0b6d0a.png"></p> <pre> <code class="language-java">package com.castiel.dao; import de.greenrobot.daogenerator.DaoGenerator; import de.greenrobot.daogenerator.Entity; import de.greenrobot.daogenerator.Schema; public class CastielGreenDao { public static void main(String args[]) throws Exception { // 创建了一个用于添加实体(Entity)的模式(Schema)对象。 // 两个参数分别代表:数据库版本号与自动生成代码的包路径。 Schema schema = new Schema(1, "greendao"); schema.setDefaultJavaPackageDao("com.castiel.dao"); // 一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。 addNote(schema); // 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。 new DaoGenerator().generateAll(schema, args[0]); } /** * @param schema */ private static void addNote(Schema schema) { // 一个实体(类)就关联到数据库中的一张表,此处表名为「Student」(既类名) Entity note = schema.addEntity("Student"); // 你也可以重新给表命名 // note.setTableName("Student2"); // greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值 // 接下来你便可以设置表中的字段: // 与在 Java 中使用驼峰命名法不同,默认数据库中的命名是使用大写和下划线来分割单词的。 note.addIdProperty(); note.addStringProperty("sName").notNull(); note.addStringProperty("sAge"); note.addStringProperty("sSex"); note.addStringProperty("sClass"); } }</code></pre> <h3>3.生成 DAO 文件(数据库)</h3> <p>执行 generator 工程,如一切正常,你将会在控制台看到如下日志,并且在主工程「java-gen」下会发现生成了DaoMaster、DaoSession、StudentDao、Student共4个类文件。</p> <pre> <code>greenDAO Generator Copyright 2011-2013 Markus Junginger, greenrobot.de. Licensed under GPL V3. This program comes with ABSOLUTELY NO WARRANTY Processing schema version 1... Written C:\Users\huangshuai\AndroidStudioProjects\CastielGreenDao\app\src\main\java-gen\com\castiel\dao\StudentDao.java Written C:\Users\huangshuai\AndroidStudioProjects\CastielGreenDao\app\src\main\java-gen\greendao\Student.java Written C:\Users\huangshuai\AndroidStudioProjects\CastielGreenDao\app\src\main\java-gen\com\castiel\dao\DaoMaster.java Written C:\Users\huangshuai\AndroidStudioProjects\CastielGreenDao\app\src\main\java-gen\com\castiel\dao\DaoSession.java Processed 1 entities in 153ms BUILD SUCCESSFUL</code></pre> <h2>构建Android项目实现增删改查</h2> <p><strong>先来张项目结构全景图</strong></p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/86be2628a5800d6e587ec96414735801.png"></p> <p><strong>再来张项目效果图</strong></p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/9643580277b72f0ddb92f37463a8b2f7.png"></p> <p><strong>在官网中,提供了一段核心初始化代码,推荐将该段代码放在Application中</strong></p> <pre> <code class="language-java">helper = new DaoMaster.DevOpenHelper( this, "notes-db", null); db = helper.getWritableDatabase(); daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession(); noteDao = daoSession.getNoteDao();</code></pre> <p>即:在自己的Application中先创建了一个SQLiteOpenHelper并创建连接到一个具体数据库;再根据具体的datebase创建一个master对象用于;最后通过master创建一个数据库的会话操作。</p> <pre> <code class="language-java">package com.castiel.dao; import android.app.Application; import android.database.sqlite.SQLiteDatabase; /** * Created by huangshuai on 2016/5/11. * Email:huangshuai@wooyun.org */ public class BaseApplication extends Application { public DaoSession daoSession; public SQLiteDatabase db; public DaoMaster.DevOpenHelper helper; public DaoMaster daoMaster; @Override public void onCreate() { super.onCreate(); setupDatabase(); } private void setupDatabase() { // 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 SQLiteOpenHelper 对象。 // 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。 // 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。 // 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。 helper = new DaoMaster.DevOpenHelper(this, "student", null); db = helper.getWritableDatabase(); // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。 daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession(); } public DaoSession getDaoSession() { return daoSession; } public SQLiteDatabase getDb() { return db; } }</code></pre> <p><strong>Activity具体实现</strong></p> <pre> <code class="language-java">package com.castiel.dao; import android.app.Activity; import android.app.Dialog; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import java.util.List; import de.greenrobot.dao.query.Query; import greendao.Student; /** * Created by huangshuai on 2016/5/11. * Email:huangshuai@wooyun.org * GreenDao增删改查实例 */ public class CastielActivity extends Activity implements StudentAdapter.AdapterEnterCallBack{ // 初始化组件 public static final String TAG = "WY"; private List<Student> listStudent; private ListView list; private EditText etQureyName; StudentAdapter studentAdapter; private Button btnAdd,btnQurey; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_dao); list = (ListView) findViewById(R.id.dao_list); btnAdd = (Button) findViewById(R.id.btn_add); btnQurey = (Button) findViewById(R.id.btn_query); etQureyName = (EditText) findViewById(R.id.edit_query); listStudent = getStudentDao().loadAll();// 查询全部数据操作 studentAdapter = new StudentAdapter(CastielActivity.this,listStudent); list.setAdapter(studentAdapter); studentAdapter.setCallback(this); btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialogAdd(); } }); btnQurey.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String curCondition = etQureyName.getText().toString().trim(); if (TextUtils.isEmpty(curCondition)) { Toast.makeText(CastielActivity.this,"查询条件不能为空",Toast.LENGTH_SHORT).show(); } else { // Query 类代表了一个可以被重复执行的查询 Query query = getStudentDao().queryBuilder() .where(StudentDao.Properties.SName.eq(curCondition)) .build(); // 查询结果以 List 返回 List students = query.list(); Toast.makeText(CastielActivity.this,"有" + students.size() + "个条件符合",Toast.LENGTH_SHORT).show(); } etQureyName.setText("");// 查询后重置条件 } }); } /** * 通过 BaseApplication 类提供的 getDaoSession() 获取具体 Dao * @return */ private StudentDao getStudentDao() { return ((BaseApplication) this.getApplicationContext()).getDaoSession().getStudentDao(); } /** * 通过 BaseApplication 类提供的 getDb() 获取具体 db * @return */ private SQLiteDatabase getDb() { return ((BaseApplication) this.getApplicationContext()).getDb(); } /** * 添加操作弹窗 */ protected void dialogAdd() { final Dialog dataDialog = new Dialog(CastielActivity.this,R.style.myDialogTheme); LayoutInflater curInfnfalater = LayoutInflater.from(this); View view = curInfnfalater.inflate(R.layout.my_dialog, null); Button b_ok,b_cancle; final EditText etName,etSex,etClass,etAge; etName = (EditText) view.findViewById(R.id.edit_name); etSex = (EditText) view.findViewById(R.id.edit_sex); etClass = (EditText) view.findViewById(R.id.edit_class); etAge = (EditText) view.findViewById(R.id.edit_age); b_ok = (Button) view.findViewById(R.id.btn_ok); b_ok.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { Student ss = new Student(null,etName.getText().toString().trim(),etAge.getText().toString().trim(),etSex.getText().toString().trim(),etClass.getText().toString().trim()); getStudentDao().insert(ss); studentAdapter.addData(ss); dataDialog.dismiss(); } }); b_cancle = (Button) view.findViewById(R.id.btn_cancel); b_cancle.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { dataDialog.dismiss(); } }); dataDialog.setContentView(view); dataDialog.show(); } /** * 修改操作弹窗 */ protected void dialogModify(final Student curBean) { final Dialog dataDialog = new Dialog(CastielActivity.this,R.style.myDialogTheme); LayoutInflater curInfnfalater = LayoutInflater.from(this); View view = curInfnfalater.inflate(R.layout.my_dialog, null); Button b_ok,b_cancle; final EditText etName,etSex,etClass,etAge; etName = (EditText) view.findViewById(R.id.edit_name); etSex = (EditText) view.findViewById(R.id.edit_sex); etClass = (EditText) view.findViewById(R.id.edit_class); etAge = (EditText) view.findViewById(R.id.edit_age); etName.setText(curBean.getSName()); etSex.setText(curBean.getSSex()); etClass.setText(curBean.getSClass()); etAge.setText(curBean.getSAge()); b_ok = (Button) view.findViewById(R.id.btn_ok); b_ok.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { Student ss = new Student(curBean.getId(),etName.getText().toString().trim(),etAge.getText().toString().trim(),etSex.getText().toString().trim(),etClass.getText().toString().trim()); getStudentDao().deleteByKey(curBean.getId()); getStudentDao().insert(ss); studentAdapter.setData(getStudentDao().loadAll()); dataDialog.dismiss(); } }); b_cancle = (Button) view.findViewById(R.id.btn_cancel); b_cancle.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { dataDialog.dismiss(); } }); dataDialog.setContentView(view); dataDialog.show(); } /**菜单弹窗 */ protected void dialogMenu(final Student curBean) { final Dialog dataDialog = new Dialog(CastielActivity.this,R.style.myDialogTheme); LayoutInflater curInfnfalater = LayoutInflater.from(this); View view = curInfnfalater.inflate(R.layout.item_dialog, null); Button b_modify,b_del; b_modify = (Button) view.findViewById(R.id.btn_modify); b_modify.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { dialogModify(curBean); dataDialog.dismiss(); } }); b_del = (Button) view.findViewById(R.id.btn_del); b_del.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { // 根据Id删除对应数据 getStudentDao().deleteByKey(curBean.getId()); studentAdapter.setData(getStudentDao().loadAll()); dataDialog.dismiss(); } }); dataDialog.setContentView(view); dataDialog.show(); } @Override public void onEnterClick(Student bean) { dialogMenu(bean); } }</code></pre> <p><strong>列表相关Adapter</strong></p> <pre> <code class="language-java">package com.castiel.dao; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.TextView; import java.util.List; import greendao.Student; /** * Created by huangshuai on 2016/5/11. * Email:huangshuai@wooyun.org * Student列表的Adapter */ public class StudentAdapter extends BaseAdapter { private AdapterEnterCallBack callback; private LayoutInflater inflater; private List<Student> list_student; public StudentAdapter(Context context, List<Student> list_student) { this.inflater = LayoutInflater.from(context); this.list_student = list_student; } @Override public int getCount() { return list_student.size(); } @Override public Object getItem(int position) { return list_student.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { StudentViewHodler sv; if (convertView == null) { sv = new StudentViewHodler(); convertView = inflater.inflate(R.layout.list_item, null); sv.uAge = (TextView) convertView.findViewById(R.id.tv_age); sv.uName = (TextView) convertView.findViewById(R.id.tv_name); sv.uSex = (TextView) convertView.findViewById(R.id.tv_sex); sv.uClass = (TextView) convertView.findViewById(R.id.tv_class); sv.litem = (LinearLayout) convertView.findViewById(R.id.ll_item); convertView.setTag(sv); } else { sv = (StudentViewHodler) convertView.getTag(); } sv.uSex.setText(list_student.get(position).getSSex()); sv.uName.setText(list_student.get(position).getSName()); sv.uAge.setText(list_student.get(position).getSAge()); sv.uClass.setText(list_student.get(position).getSClass()); sv.litem.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != callback) { callback.onEnterClick(list_student.get(position)); } } }); return convertView; } public void addData(Student data) { if (data != null) { this.list_student.add(data); notifyDataSetChanged(); } } public void setData(List<Student> data) { if (data != null) { list_student.clear(); list_student.addAll(data); notifyDataSetChanged(); } } public class StudentViewHodler { TextView uName; TextView uSex; TextView uAge; TextView uClass; LinearLayout litem; } public interface AdapterEnterCallBack { void onEnterClick(Student bean); } public void setCallback(AdapterEnterCallBack callback) { this.callback = callback; } }</code></pre> <p><strong>布局文件实现</strong></p> <p>item_dialog.xml</p> <pre> <code class="language-xml"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" android:background="@android:color/white" android:orientation="horizontal"> <Button android:id="@+id/btn_del" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="删除" /> <Button android:id="@+id/btn_modify" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="修改" /> </LinearLayout></code></pre> <p>list_item.xml</p> <pre> <code class="language-xhtml"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_name" android:layout_width="0dp" android:layout_height="24dp" android:layout_weight="1" android:textSize="22sp" android:text="姓名" /> <TextView android:id="@+id/tv_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="22sp" android:text="年龄"/> <TextView android:id="@+id/tv_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="22sp" android:text="性别"/> <TextView android:id="@+id/tv_class" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="22sp" android:text="班级"/> </LinearLayout></code></pre> <p>main_dao.xml</p> <pre> <code class="language-xhtml"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_add" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="增加数据" /> <Button android:id="@+id/btn_query" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="姓名查询" /> <EditText android:id="@+id/edit_query" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="输入姓名" android:textColor="@android:color/black" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_name" android:layout_width="0dp" android:layout_height="24dp" android:layout_weight="1" android:textSize="18sp" android:text="姓名" /> <TextView android:id="@+id/tv_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="18sp" android:text="年龄"/> <TextView android:id="@+id/tv_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="18sp" android:text="性别"/> <TextView android:id="@+id/tv_class" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="18sp" android:text="班级"/> </LinearLayout> <ListView android:id="@+id/dao_list" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout></code></pre> <p>my_dialog.xml</p> <pre> <code class="language-xhtml"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="姓名:" /> <EditText android:id="@+id/edit_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="性别:" /> <EditText android:id="@+id/edit_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="班级:" /> <EditText android:id="@+id/edit_class" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="年龄:" /> <EditText android:id="@+id/edit_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> </LinearLayout> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_ok" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="确认" /> <Button android:id="@+id/btn_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" /> </LinearLayout> </LinearLayout></code></pre> <h3>运行程序,执行增删改查</h3> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/b60c666a415ab01a7622373289fb784c.png"></p> <p><img alt="这里写图片描述" src="https://simg.open-open.com/show/f5081c6aabf4e6d53b851766ec47d64c.png"></p> <p><strong>项目源码链接:</strong><a href="/misc/goto?guid=4959673067649313387">http://download.csdn.net/detail/mynameishuangshuai/9518322</a></p> <p>参考链接:<a href="http://www.open-open.com/lib/view/open1438065400878.html">http://itangqi.me/2015/07/26/orm-greendao-summary/</a></p> <p>via: http://blog.csdn.net/mynameishuangshuai/article/details/51386402</p>