大家的项目中不可避免的使用到SQLite,为此我们要花费心思编写一个增删改查框架。而一个好的ORM框架则能够给我们带来极大的方便,今天给大家讲解一个非常火热的ORM-GreenDao。
基本概念
GreenDao官网地址:http://greenrobot.org/greendao/
官网对GreenDao的介绍:
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.
简单的说就是:greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。
greenDAO 设计的主要目标
- 一个精简的库
- 性能最大化
- 内存开销最小化
- 易于使用的 APIs
- 对 Android 进行高度优化
greenDAO 设计的主要特点
- greenDAO 性能远远高于同类的 ORMLite,具体测试结果可见官网
- greenDAO 支持 protocol buffer(protobuf) 协议数据的直接存储,如果你通过 protobuf
协议与服务器交互,将不需要任何的映射。 - 与 ORMLite 等使用注解方式的 ORM 框架不同,greenDAO 使用「Code
generation」的方式,这也是其性能能大幅提升的原因。
Dao项目代码生成
DaoMaster:一看名字就知道它是Dao中的最大的官了。它保存了sqlitedatebase对象以及操作DAO classes(注意:不是对象)。其提供了一些创建和删除table的静态方法,其内部类OpenHelper和DevOpenHelper实现了SQLiteOpenHelper并创建数据库的框架。
DaoSession:会话层。操作具体的DAO对象(注意:是对象),比如各种getter方法。
XXXDao:实际生成的某某DAO类,通常对应具体的java类,比如NoteDao等。其有更多的权限和方法来操作数据库元素。
XXXEntity:持久的实体对象。通常代表了一个数据库row的标准java properties。
了解了基本概念后我们开始动手完成一个增删改查的项目案例。
实现过程
1.在 Android 工程中配置「greenDao Generator」模块
在 .src/main 目录下新建一个与 java 同层级的「java-gen」目录,用于存放由 greenDAO 生成的 Bean、DAO、DaoMaster、DaoSession 等类。
配置 Android 工程(app)的 build.gradle,如图分别添加 sourceSets 与 dependencies
1 sourceSets { 2 main { 3 java.srcDirs = ['src/main/java', 'src/main/java-gen'] 4 } 5 }
1 compile 'de.greenrobot:greendao:1.3.7'
2.新建「greenDAO Generator」模块 (纯 Java 工程)
通过 File -> New -> New Module -> Java Library -> 填写相应的包名与类名 -> Finish
配置 castielgreendaolb 工程的 build.gradle,添加 dependencie
注意主句话,配置输出路径
1 def outputDir = "../app/src/main/java-gen"
接着,编写 CastielGreenDao类,注意: 我们的 Java 工程只有一个类,它的内容决定了「GreenDao Generator」的输出,你可以在这个类中通过对象、关系等创建数据库结构,下面我将以注释的形式详细讲解代码内容。
1 package com.castiel.dao; 2 3 import de.greenrobot.daogenerator.DaoGenerator; 4 import de.greenrobot.daogenerator.Entity; 5 import de.greenrobot.daogenerator.Schema; 6 7 public class CastielGreenDao { 8 public static void main(String args[]) throws Exception { 9 // 创建了一个用于添加实体(Entity)的模式(Schema)对象。 10 // 两个参数分别代表:数据库版本号与自动生成代码的包路径。 11 Schema schema = new Schema(1, "greendao"); 12 schema.setDefaultJavaPackageDao("com.castiel.dao"); 13 14 // 一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。 15 addNote(schema); 16 17 // 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。 18 new DaoGenerator().generateAll(schema, args[0]); 19 } 20 21 /** * @param schema */ 22 private static void addNote(Schema schema) { 23 // 一个实体(类)就关联到数据库中的一张表,此处表名为「Student」(既类名) 24 Entity note = schema.addEntity("Student"); 25 // 你也可以重新给表命名 26 // note.setTableName("Student2"); 27 28 // greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值 29 // 接下来你便可以设置表中的字段: 30 // 与在 Java 中使用驼峰命名法不同,默认数据库中的命名是使用大写和下划线来分割单词的。 31 note.addIdProperty(); 32 note.addStringProperty("sName").notNull(); 33 note.addStringProperty("sAge"); 34 note.addStringProperty("sSex"); 35 note.addStringProperty("sClass"); 36 } 37 }
3.生成 DAO 文件(数据库)
执行 generator 工程,如一切正常,你将会在控制台看到如下日志,并且在主工程「java-gen」下会发现生成了DaoMaster、DaoSession、StudentDao、Student共4个类文件。
1 greenDAO Generator 2 Copyright 2011-2013 Markus Junginger, greenrobot.de. Licensed under GPL V3. 3 This program comes with ABSOLUTELY NO WARRANTY 4 Processing schema version 1... 5 Written C:UsershuangshuaiAndroidStudioProjectsCastielGreenDaoappsrcmainjava-gencomcastieldaoStudentDao.java 6 Written C:UsershuangshuaiAndroidStudioProjectsCastielGreenDaoappsrcmainjava-gengreendaoStudent.java 7 Written C:UsershuangshuaiAndroidStudioProjectsCastielGreenDaoappsrcmainjava-gencomcastieldaoDaoMaster.java 8 Written C:UsershuangshuaiAndroidStudioProjectsCastielGreenDaoappsrcmainjava-gencomcastieldaoDaoSession.java 9 Processed 1 entities in 153ms 10 11 BUILD SUCCESSFUL
构建Android项目实现增删改查
先来张项目结构全景图
再来张项目效果图
在官网中,提供了一段核心初始化代码,推荐将该段代码放在Application中
1 helper = new DaoMaster.DevOpenHelper( this, "notes-db", null); 2 db = helper.getWritableDatabase(); 3 daoMaster = new DaoMaster(db); 4 daoSession = daoMaster.newSession(); 5 noteDao = daoSession.getNoteDao();
即:在自己的Application中先创建了一个SQLiteOpenHelper并创建连接到一个具体数据库;再根据具体的datebase创建一个master对象用于;最后通过master创建一个数据库的会话操作。
1 package com.castiel.dao; 2 3 import android.app.Application; 4 import android.database.sqlite.SQLiteDatabase; 5 6 /** * Created by huangshuai on 2016/5/11. * Email:huangshuai@wooyun.org */ 7 public class BaseApplication extends Application { 8 public DaoSession daoSession; 9 public SQLiteDatabase db; 10 public DaoMaster.DevOpenHelper helper; 11 public DaoMaster daoMaster; 12 13 @Override 14 public void onCreate() { 15 super.onCreate(); 16 setupDatabase(); 17 } 18 19 private void setupDatabase() { 20 // 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 SQLiteOpenHelper 对象。 21 // 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。 22 // 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。 23 // 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。 24 helper = new DaoMaster.DevOpenHelper(this, "student", null); 25 db = helper.getWritableDatabase(); 26 // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。 27 daoMaster = new DaoMaster(db); 28 daoSession = daoMaster.newSession(); 29 } 30 31 public DaoSession getDaoSession() { 32 return daoSession; 33 } 34 35 public SQLiteDatabase getDb() { 36 return db; 37 } 38 39 }
Activity具体实现
1 package com.castiel.dao; 2 3 import android.app.Activity; 4 import android.app.Dialog; 5 import android.database.sqlite.SQLiteDatabase; 6 import android.os.Bundle; 7 import android.text.TextUtils; 8 import android.view.LayoutInflater; 9 import android.view.View; 10 import android.widget.Button; 11 import android.widget.EditText; 12 import android.widget.ListView; 13 import android.widget.Toast; 14 15 import java.util.List; 16 17 import de.greenrobot.dao.query.Query; 18 import greendao.Student; 19 20 /** * Created by huangshuai on 2016/5/11. * Email:huangshuai@wooyun.org * GreenDao增删改查实例 */ 21 public class CastielActivity extends Activity implements StudentAdapter.AdapterEnterCallBack{ 22 // 初始化组件 23 public static final String TAG = "WY"; 24 private List<Student> listStudent; 25 private ListView list; 26 private EditText etQureyName; 27 StudentAdapter studentAdapter; 28 private Button btnAdd,btnQurey; 29 @Override 30 public void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.main_dao); 33 list = (ListView) findViewById(R.id.dao_list); 34 btnAdd = (Button) findViewById(R.id.btn_add); 35 btnQurey = (Button) findViewById(R.id.btn_query); 36 etQureyName = (EditText) findViewById(R.id.edit_query); 37 listStudent = getStudentDao().loadAll();// 查询全部数据操作 38 studentAdapter = new StudentAdapter(CastielActivity.this,listStudent); 39 40 list.setAdapter(studentAdapter); 41 studentAdapter.setCallback(this); 42 43 btnAdd.setOnClickListener(new View.OnClickListener() { 44 @Override 45 public void onClick(View v) { 46 dialogAdd(); 47 } 48 }); 49 50 btnQurey.setOnClickListener(new View.OnClickListener() { 51 @Override 52 public void onClick(View v) { 53 String curCondition = etQureyName.getText().toString().trim(); 54 if (TextUtils.isEmpty(curCondition)) { 55 Toast.makeText(CastielActivity.this,"查询条件不能为空",Toast.LENGTH_SHORT).show(); 56 } else { 57 // Query 类代表了一个可以被重复执行的查询 58 Query query = getStudentDao().queryBuilder() 59 .where(StudentDao.Properties.SName.eq(curCondition)) 60 .build(); 61 // 查询结果以 List 返回 62 List students = query.list(); 63 Toast.makeText(CastielActivity.this,"有" + students.size() + "个条件符合",Toast.LENGTH_SHORT).show(); 64 } 65 etQureyName.setText("");// 查询后重置条件 66 } 67 }); 68 } 69 70 /** * 通过 BaseApplication 类提供的 getDaoSession() 获取具体 Dao * @return */ 71 private StudentDao getStudentDao() { 72 return ((BaseApplication) this.getApplicationContext()).getDaoSession().getStudentDao(); 73 } 74 75 /** * 通过 BaseApplication 类提供的 getDb() 获取具体 db * @return */ 76 private SQLiteDatabase getDb() { 77 return ((BaseApplication) this.getApplicationContext()).getDb(); 78 } 79 80 /** * 添加操作弹窗 */ 81 protected void dialogAdd() { 82 final Dialog dataDialog = new Dialog(CastielActivity.this,R.style.myDialogTheme); 83 LayoutInflater curInfnfalater = LayoutInflater.from(this); 84 View view = curInfnfalater.inflate(R.layout.my_dialog, null); 85 Button b_ok,b_cancle; 86 final EditText etName,etSex,etClass,etAge; 87 etName = (EditText) view.findViewById(R.id.edit_name); 88 etSex = (EditText) view.findViewById(R.id.edit_sex); 89 etClass = (EditText) view.findViewById(R.id.edit_class); 90 etAge = (EditText) view.findViewById(R.id.edit_age); 91 92 93 b_ok = (Button) view.findViewById(R.id.btn_ok); 94 b_ok.setOnClickListener(new Button.OnClickListener() { 95 public void onClick(View v) { 96 Student ss = new Student(null,etName.getText().toString().trim(),etAge.getText().toString().trim(),etSex.getText().toString().trim(),etClass.getText().toString().trim()); 97 getStudentDao().insert(ss); 98 studentAdapter.addData(ss); 99 dataDialog.dismiss(); 100 } 101 }); 102 b_cancle = (Button) view.findViewById(R.id.btn_cancel); 103 b_cancle.setOnClickListener(new Button.OnClickListener() { 104 public void onClick(View v) { 105 dataDialog.dismiss(); 106 } 107 }); 108 109 110 dataDialog.setContentView(view); 111 dataDialog.show(); 112 } 113 114 /** * 修改操作弹窗 */ 115 protected void dialogModify(final Student curBean) { 116 final Dialog dataDialog = new Dialog(CastielActivity.this,R.style.myDialogTheme); 117 LayoutInflater curInfnfalater = LayoutInflater.from(this); 118 View view = curInfnfalater.inflate(R.layout.my_dialog, null); 119 Button b_ok,b_cancle; 120 final EditText etName,etSex,etClass,etAge; 121 etName = (EditText) view.findViewById(R.id.edit_name); 122 etSex = (EditText) view.findViewById(R.id.edit_sex); 123 etClass = (EditText) view.findViewById(R.id.edit_class); 124 etAge = (EditText) view.findViewById(R.id.edit_age); 125 etName.setText(curBean.getSName()); 126 etSex.setText(curBean.getSSex()); 127 etClass.setText(curBean.getSClass()); 128 etAge.setText(curBean.getSAge()); 129 130 b_ok = (Button) view.findViewById(R.id.btn_ok); 131 b_ok.setOnClickListener(new Button.OnClickListener() { 132 public void onClick(View v) { 133 Student ss = new Student(curBean.getId(),etName.getText().toString().trim(),etAge.getText().toString().trim(),etSex.getText().toString().trim(),etClass.getText().toString().trim()); 134 getStudentDao().deleteByKey(curBean.getId()); 135 getStudentDao().insert(ss); 136 studentAdapter.setData(getStudentDao().loadAll()); 137 dataDialog.dismiss(); 138 } 139 }); 140 b_cancle = (Button) view.findViewById(R.id.btn_cancel); 141 b_cancle.setOnClickListener(new Button.OnClickListener() { 142 public void onClick(View v) { 143 dataDialog.dismiss(); 144 } 145 }); 146 147 148 dataDialog.setContentView(view); 149 dataDialog.show(); 150 } 151 152 /**菜单弹窗 */ 153 protected void dialogMenu(final Student curBean) { 154 final Dialog dataDialog = new Dialog(CastielActivity.this,R.style.myDialogTheme); 155 LayoutInflater curInfnfalater = LayoutInflater.from(this); 156 View view = curInfnfalater.inflate(R.layout.item_dialog, null); 157 Button b_modify,b_del; 158 159 b_modify = (Button) view.findViewById(R.id.btn_modify); 160 b_modify.setOnClickListener(new Button.OnClickListener() { 161 public void onClick(View v) { 162 dialogModify(curBean); 163 dataDialog.dismiss(); 164 } 165 }); 166 b_del = (Button) view.findViewById(R.id.btn_del); 167 b_del.setOnClickListener(new Button.OnClickListener() { 168 public void onClick(View v) { 169 // 根据Id删除对应数据 170 getStudentDao().deleteByKey(curBean.getId()); 171 studentAdapter.setData(getStudentDao().loadAll()); 172 dataDialog.dismiss(); 173 } 174 }); 175 176 177 dataDialog.setContentView(view); 178 dataDialog.show(); 179 } 180 181 @Override 182 public void onEnterClick(Student bean) { 183 dialogMenu(bean); 184 } 185 }
列表相关Adapter
1 package com.castiel.dao; 2 3 import android.content.Context; 4 import android.view.LayoutInflater; 5 import android.view.View; 6 import android.view.ViewGroup; 7 import android.widget.BaseAdapter; 8 import android.widget.LinearLayout; 9 import android.widget.TextView; 10 11 import java.util.List; 12 13 import greendao.Student; 14 15 /** * Created by huangshuai on 2016/5/11. * Email:huangshuai@wooyun.org * Student列表的Adapter */ 16 public class StudentAdapter extends BaseAdapter { 17 private AdapterEnterCallBack callback; 18 private LayoutInflater inflater; 19 private List<Student> list_student; 20 21 public StudentAdapter(Context context, List<Student> list_student) { 22 this.inflater = LayoutInflater.from(context); 23 this.list_student = list_student; 24 } 25 26 @Override 27 public int getCount() { 28 return list_student.size(); 29 } 30 31 @Override 32 public Object getItem(int position) { 33 return list_student.get(position); 34 } 35 36 @Override 37 public long getItemId(int position) { 38 return position; 39 } 40 41 @Override 42 public View getView(final int position, View convertView, ViewGroup parent) { 43 StudentViewHodler sv; 44 if (convertView == null) { 45 sv = new StudentViewHodler(); 46 convertView = inflater.inflate(R.layout.list_item, null); 47 sv.uAge = (TextView) convertView.findViewById(R.id.tv_age); 48 sv.uName = (TextView) convertView.findViewById(R.id.tv_name); 49 sv.uSex = (TextView) convertView.findViewById(R.id.tv_sex); 50 sv.uClass = (TextView) convertView.findViewById(R.id.tv_class); 51 sv.litem = (LinearLayout) convertView.findViewById(R.id.ll_item); 52 53 convertView.setTag(sv); 54 } else { 55 sv = (StudentViewHodler) convertView.getTag(); 56 } 57 58 sv.uSex.setText(list_student.get(position).getSSex()); 59 sv.uName.setText(list_student.get(position).getSName()); 60 sv.uAge.setText(list_student.get(position).getSAge()); 61 sv.uClass.setText(list_student.get(position).getSClass()); 62 sv.litem.setOnClickListener(new View.OnClickListener() { 63 @Override 64 public void onClick(View v) { 65 if (null != callback) { 66 callback.onEnterClick(list_student.get(position)); 67 } 68 } 69 }); 70 return convertView; 71 } 72 73 public void addData(Student data) { 74 if (data != null) { 75 this.list_student.add(data); 76 notifyDataSetChanged(); 77 } 78 } 79 80 public void setData(List<Student> data) { 81 if (data != null) { 82 list_student.clear(); 83 list_student.addAll(data); 84 notifyDataSetChanged(); 85 } 86 } 87 88 public class StudentViewHodler { 89 TextView uName; 90 TextView uSex; 91 TextView uAge; 92 TextView uClass; 93 LinearLayout litem; 94 } 95 96 public interface AdapterEnterCallBack { 97 void onEnterClick(Student bean); 98 } 99 100 public void setCallback(AdapterEnterCallBack callback) { 101 this.callback = callback; 102 } 103 104 }
布局文件实现
item_dialog.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <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"> 3 4 <Button android:id="@+id/btn_del" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="删除" /> 5 6 <Button android:id="@+id/btn_modify" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="修改" /> 7 </LinearLayout>
list_item.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <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"> 3 4 <TextView android:id="@+id/tv_name" android:layout_width="0dp" android:layout_height="24dp" android:layout_weight="1" android:textSize="22sp" android:text="姓名" /> 5 6 <TextView android:id="@+id/tv_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="22sp" android:text="年龄"/> 7 8 <TextView android:id="@+id/tv_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="22sp" android:text="性别"/> 9 10 <TextView android:id="@+id/tv_class" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="22sp" android:text="班级"/> 11 12 </LinearLayout>
main_dao.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> 3 4 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> 5 6 <Button android:id="@+id/btn_add" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="增加数据" /> 7 8 <Button android:id="@+id/btn_query" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="姓名查询" /> 9 10 <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" /> 11 </LinearLayout> 12 13 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> 14 15 <TextView android:id="@+id/tv_name" android:layout_width="0dp" android:layout_height="24dp" android:layout_weight="1" android:textSize="18sp" android:text="姓名" /> 16 17 <TextView android:id="@+id/tv_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="18sp" android:text="年龄"/> 18 19 <TextView android:id="@+id/tv_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="18sp" android:text="性别"/> 20 21 <TextView android:id="@+id/tv_class" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="18sp" android:text="班级"/> 22 23 </LinearLayout> 24 25 26 <ListView android:id="@+id/dao_list" android:layout_width="match_parent" android:layout_height="wrap_content"/> 27 </LinearLayout>
my_dialog.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <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"> 3 4 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> 5 6 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> 7 8 <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> 9 10 <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="姓名:" /> 11 12 <EditText android:id="@+id/edit_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> 13 </LinearLayout> 14 15 <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> 16 17 <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="性别:" /> 18 19 <EditText android:id="@+id/edit_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> 20 </LinearLayout> 21 </LinearLayout> 22 23 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> 24 25 <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> 26 27 <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="班级:" /> 28 29 <EditText android:id="@+id/edit_class" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> 30 </LinearLayout> 31 32 <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> 33 34 <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="年龄:" /> 35 36 <EditText android:id="@+id/edit_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@android:color/black" /> 37 </LinearLayout> 38 </LinearLayout> 39 40 </LinearLayout> 41 42 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> 43 44 <Button android:id="@+id/btn_ok" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="确认" /> 45 46 <Button android:id="@+id/btn_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" /> 47 </LinearLayout> 48 </LinearLayout>
运行程序,执行增删改查
项目源码链接:http://download.csdn.net/detail/mynameishuangshuai/9518322
参考链接:http://itangqi.me/2015/07/26/orm-greendao-summary/
via: http://blog.csdn.net/mynameishuangshuai/article/details/51386402