快速入门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>