<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                在上一篇博客[《打造android ORM框架opendroid(一)——ORM框架的使用》](http://blog.csdn.net/qibin0506/article/details/42736807)中相信你已經了解了opendroid的使用,那么從這篇博客開始,我們正式進入opendroid的源碼分析,打造一款自己的ORM框架! 在正式開始之前,你需要保證手里有一份opendroid的源碼,如果還沒下載opendroid,請到[http://git.oschina.net/qibin/OpenDroid](http://git.oschina.net/qibin/OpenDroid)?下載opendroid的源碼。 任何數據庫操作都是從創建數據庫開始的,今天我們就來看看opendroid是怎么幫我們自動創建數據庫的。 還記得關系映射怎么配置嗎? 在open-droid.xml中,通過配置mapping節點來告訴opendroid我們需要映射的java bean。那么數據庫操作是從何時開始的呢, 拿insert來說,就是調用了從OpenDroid繼承而來的save()方法!在這之前,我們沒有任何數據庫方面的操作,那么我們就從save()方法開始,看看opendroid是怎么創建數據庫的。 ~~~ /**? ?*?插入數據? ?*?@return?最后插入的id? */?? public?long?save()?{?? ????try?{?? ????????Class?klass?=?(Class)?getClass();?? ????????ContentValues?cv?=?new?ContentValues();?? ????????generateData(klass,?cv);?? ?????????????? ????????return?CRUD.insert(klass.getSimpleName(),?cv,?sSqliteDatabase);?? ????}?catch?(Exception?e)?{?? ????????e.printStackTrace();?? ????}?? ????return?-1;?? }?? ~~~ 第11行,通過調用了CRUD的一個靜態方法insert將數據保存到數據庫中,insert的最后一個參數sSqliteDatabas是我們關心的,來看看它的定義: ~~~ private?static?SQLiteDatabase?sSqliteDatabase?=?sOpenHelper.getWritableDatabase();?? ~~~ sSqliteDatabase是通過sOpenHelper調用getWriteableDatabase()返回的,相信這里大家應該非常熟悉了,再來看看sOpenHelper的定義: ` private?static?CreateDB?sOpenHelper?=?new?CreateDB();??` 在這里直接new了一個CreateDB,通過類名我們完全可以知道CreateDB就是創建數據庫的關鍵。來看看CreateDB吧: ~~~ public?class?CreateDB?extends?SQLiteOpenHelper?{?? ?????? ????public?CreateDB()?{?? ????????super(DroidApplication.sContext,?OpenDroidHelper.getDBInfoBean().getName(),?? ????????????????null,?OpenDroidHelper.getDBInfoBean().getVersion(),?new?DefaultDatabaseErrorHandler());?? ????}?? ?? ????@Override?? ????public?void?onCreate(SQLiteDatabase?db)?{?? ????????for(String?sql?:?OpenDroidHelper.getDBInfoBean().getSqls())?{?? ????????????db.execSQL(sql);?? ????????}?? ????}?? }?? ~~~ 這里我只截取了和創建數據庫有關的代碼, 可以看到CreateDB繼承自SQLiteOpenHelper,這里大家肯定也很熟悉,先從構造方法開始看, 在構造方法中直接調用了父類的構造方法,第一個參數是一個context對象,這個對象是在DroidApplication中,其實很簡單,就是在onCreate中調用getApplicationContext()為DroidApplication中的sContext靜態變量賦值,這里就不貼代碼了,可以在源碼中找到,在看看接下來幾個參數,都是通過OpenDroidHelper.getDBInfoBean獲取的。再往后看看發現onCreate中也是通過遍歷OpenDroidHelper.getDBInfoBean().getSqls()來獲取創建表的sql語句,那么現在我們就去OpenDroidHelper看看吧。 ~~~ public?class?OpenDroidHelper?{?? ????public?static?final?String?TAG_DROID?=?"open-droid";?? ????public?static?final?String?TAG_VERSION?=?"version";?? ????public?static?final?String?TAG_NAME?=?"name";?? ????public?static?final?String?TAG_MAPPING?=?"mapping";?? ?????? ????private?static?DBBean?sDBBean;?? ?????? ????public?static?DBBean?getDBInfoBean()?{?? ????????if(sDBBean?==?null)?{?? ????????????generateDBInfoBean();?? ????????}?? ?????????? ????????return?sDBBean;?? ????}?? ?????? ????/**? ?????*?解析Asserts目錄下的open_droid.xml文件,生成DBInfoBean? ?????*/?? ????private?static?void?generateDBInfoBean()?{?? ????????try?{?? ????????????XmlPullParser?pullParser?=?Xml.newPullParser();?? ????????????InputStream?inputStream?=?DroidApplication.sContext.getAssets().open("open_droid.xml");?? ????????????pullParser.setInput(inputStream,?"utf-8");?? ?????????????? ????????????int?type?=?pullParser.getEventType();?? ????????????String?tagName?=?null;?? ?????????????? ????????????while(type?!=?XmlPullParser.END_DOCUMENT)?{?? ????????????????if(type?==?XmlPullParser.START_TAG)?{?? ????????????????????tagName?=?pullParser.getName();?? ????????????????????if(tagName.equals(TAG_DROID))?{?? ????????????????????????sDBBean?=?new?DBBean();?? ????????????????????}else?if(tagName.equals(TAG_VERSION))?{?? ????????????????????????//?獲取版本號?? ????????????????????????sDBBean.setVersion(Integer.parseInt(pullParser.getAttributeValue(null,?"value")));?? ????????????????????}else?if(tagName.equals(TAG_NAME))?{?? ????????????????????????//?獲取數據庫名?? ????????????????????????sDBBean.setName(pullParser.getAttributeValue(null,?"value"));?? ????????????????????}else?if(tagName.equals(TAG_MAPPING))?{?? ????????????????????????//?獲取所有建表語句?? ????????????????????????sDBBean.addSql(generateSql(pullParser));?? ????????????????????}?? ????????????????}?? ????????????????type?=?pullParser.next();?? ????????????}?? ????????}?catch?(Exception?e)?{?? ????????????e.printStackTrace();?? ????????}?? ????}?? ?? ????/**? ?????*?生成建表sql語句? ?????*?@param?pullParser? ?????*?@return? ?????*?@throws?ClassNotFoundException? ?????*?@throws?XmlPullParserException? ?????*?@throws?IOException? ?????*/?? ????private?static?String?generateSql(XmlPullParser?pullParser)?? ????????????throws?ClassNotFoundException,?XmlPullParserException,?IOException?{?? ????????//?反射獲取class?? ????????Class?klass?=?(Class)?Class.forName(pullParser.getAttributeValue(null,?"class"));?? ?????????? ????????StringBuilder?sql?=?new?StringBuilder("create?table?");?? ????????//?獲取類名,?getSimpleName獲取類名,?getName()獲取包名+類名?? ????????sql.append(klass.getSimpleName()).append("(");?? ????????//?自動創建一個_id?? ????????sql.append("_id?integer?primary?key?autoincrement,");?? ?????????? ????????//?獲取所有的字段?? ????????Field[]?fields?=?klass.getDeclaredFields();?? ????????for(Field?field?:?fields)?{?? ????????????//?如果是public的,?則表示不是一個表的字段?? ????????????if(field.isAccessible())?{?? ????????????????continue;?? ????????????}?? ?????????????? ????????????//?獲取字段名?? ????????????String?name?=?field.getName();?? ????????????sql.append(name).append("?");?? ?????????????? ????????????//?獲取字段類型?? ????????????Class?fieldType?=?field.getType();?? ????????????if(fieldType?==?String.class)?{??//?如果是String?? ????????????????sql.append("text,");?? ????????????}else?if(fieldType?==?Integer.class?||?fieldType?==?int.class)?{?? ????????????????sql.append("integer,");?? ????????????}else?if(fieldType?==?Long.class?||?fieldType?==?long.class){?? ????????????????sql.append("integer,");?? ????????????}else?if(fieldType?==?Boolean.class?||?fieldType?==?boolean.class)?{?? ????????????????sql.append("boolean,");?? ????????????}else?if(fieldType?==?Float.class?||?fieldType?==?float.class)?{?? ????????????????sql.append("float,");?? ????????????}?? ????????}?? ????????sql.replace(sql.length()?-?1,?sql.length(),?"");?? ????????sql.append(");");?? ?????????? ????????return?sql.toString();?? ????}?? }?? ~~~ 額,代碼有點小長, 我們慢慢來看。首先來看看我們之前調用的getDBInfoBean(),這個方法很簡單,就是返回了一個DBBean對象,不過,它還調用了generateDBInfoBean()方法,通過方法名可以看出,它的作用是生成DBBean的。 ~~~ /**? *?解析Asserts目錄下的open_droid.xml文件,生成DBInfoBean? */?? private?static?void?generateDBInfoBean()?{?? ????try?{?? ????????XmlPullParser?pullParser?=?Xml.newPullParser();?? ????????InputStream?inputStream?=?DroidApplication.sContext.getAssets().open("open_droid.xml");?? ????????pullParser.setInput(inputStream,?"utf-8");?? ?????????????? ????????int?type?=?pullParser.getEventType();?? ????????String?tagName?=?null;?? ?????????????? ????????while(type?!=?XmlPullParser.END_DOCUMENT)?{?? ????????????if(type?==?XmlPullParser.START_TAG)?{?? ????????????????tagName?=?pullParser.getName();?? ????????????????if(tagName.equals(TAG_DROID))?{?? ????????????????????sDBBean?=?new?DBBean();?? ????????????????}else?if(tagName.equals(TAG_VERSION))?{?? ????????????????????//?獲取版本號?? ????????????????????sDBBean.setVersion(Integer.parseInt(pullParser.getAttributeValue(null,?"value")));?? ????????????????}else?if(tagName.equals(TAG_NAME))?{?? ????????????????????//?獲取數據庫名?? ????????????????????sDBBean.setName(pullParser.getAttributeValue(null,?"value"));?? ????????????????}else?if(tagName.equals(TAG_MAPPING))?{?? ????????????????????//?獲取所有建表語句?? ????????????????????sDBBean.addSql(generateSql(pullParser));?? ????????????????}?? ????????????}?? ????????????type?=?pullParser.next();?? ????????}?? ????}?catch?(Exception?e)?{?? ????????e.printStackTrace();?? ????}?? }?? ~~~ 恩,在generateDBInfoBean這個方法中,都是我們熟悉的XMLPullParser的代碼,作用就是去解析open-droid.xml文件,獲取數據庫名稱、數據庫版本和數據表的信息。雖然很長,但是都很簡單,20行,我們獲取了數據庫的版本號,并保存到了DBBean中,同樣的23行獲取了數據庫的名稱,注意第26行,我們想DBBean中添加的sql語句,那添加的什么sql語句呢? 肯定是建表的sql語句了。來看看generateSql()方法。 ~~~ /**? ?*?生成建表sql語句? ?*?@param?pullParser? ?*?@return? ?*?@throws?ClassNotFoundException? ?*?@throws?XmlPullParserException? ?*?@throws?IOException? ?*/?? private?static?String?generateSql(XmlPullParser?pullParser)?? ????????throws?ClassNotFoundException,?XmlPullParserException,?IOException?{?? ????//?反射獲取class?? ????Class?klass?=?(Class)?Class.forName(pullParser.getAttributeValue(null,?"class"));?? ?????????? ????StringBuilder?sql?=?new?StringBuilder("create?table?");?? ????//?獲取類名,?getSimpleName獲取類名,?getName()獲取包名+類名?? ????sql.append(klass.getSimpleName()).append("(");?? ????//?自動創建一個_id?? ????sql.append("_id?integer?primary?key?autoincrement,");?? ?????????? ????//?獲取所有的字段?? ????Field[]?fields?=?klass.getDeclaredFields();?? ????for(Field?field?:?fields)?{?? ????????//?如果是public的,?則表示不是一個表的字段?? ????????if(field.isAccessible())?{?? ????????????continue;?? ????????}?? ?????????????? ????????//?獲取字段名?? ????????String?name?=?field.getName();?? ????????sql.append(name).append("?");?? ?????????????? ????????//?獲取字段類型?? ????????Class?fieldType?=?field.getType();?? ????????if(fieldType?==?String.class)?{??//?如果是String?? ????????????sql.append("text,");?? ????????}else?if(fieldType?==?Integer.class?||?fieldType?==?int.class)?{?? ????????????sql.append("integer,");?? ????????}else?if(fieldType?==?Long.class?||?fieldType?==?long.class){?? ????????????sql.append("integer,");?? ????????}else?if(fieldType?==?Boolean.class?||?fieldType?==?boolean.class)?{?? ????????????sql.append("boolean,");?? ????????}else?if(fieldType?==?Float.class?||?fieldType?==?float.class)?{?? ????????????sql.append("float,");?? ????????}?? ????}?? ????sql.replace(sql.length()?-?1,?sql.length(),?"");?? ????sql.append(");");?? ?????????? ????return?sql.toString();?? }?? ~~~ generateSql()里面全是反射的代碼,如果你對反射還不熟悉,建議你先去看看java反射,因為opendroid中大量使用了反射機制, 12行,通過反射獲取我們要映射的class,然后14~18行,是初始化創建表的sql語句,并且可以看到opendroid會自動為我們添加一個_id字段,所以在定義bean的時候,我們不需要再次定義了。 21行,獲取了這個類中定義的所有字段,并在22行循環遍歷這些字段。 14~26行,可以看到,如果字段是public的,那就忽略它,所以如果你不想把某個字段映射到數據庫中,就定義成public的。 29~30行,是向創建表的sql語句中追加表名。 33~44行,通過判斷這個字段類型,來向創建表的sql語句中追加該字段的類型。 46行的作用是刪除最后一個的“,” 47行,就完成了該表的創建sql語句。 至此,opendroid的自動創建數據庫的流程我們就分析完了,現在來總結一下: 1、數據庫的創建我們借助了android API的SQLiteOpenHelper。 2、在SQLiteOpenHelper的onCreate中遍歷我們自動生成的建表語句并執行。 3、如何生成建表語句? 在OpenDroidHelper中通過反射獲取類的類名和字段名,并通過StringBuilder來拼湊建表語句。 4、為了方便,我們在OpenDroidHelper中將解析出來的數據名、數據庫版本和建表語句都放到了DBBean中,那么我們在CreateDB類中就可以通過DBBean方便的獲取數據庫的信息了。 ok,數據庫的自動創建大體流程就是這樣,在接下來的博客中,我們還會去一一介紹opendroid的CRUD操作和它的數據庫升級機制。 馬上繼續[《打造android ORM框架opendroid(三)——持久化數據》](http://blog.csdn.net/qibin0506/article/details/42872361) opendroid的開源地址:[http://git.oschina.net/qibin/OpenDroid](http://git.oschina.net/qibin/OpenDroid)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看