標籤:
首先ActiveAndroid是依靠註解工作的。
@Table(name = "UserBean")public class UserBean extends Model { @Column(name = "uid") public String uid; @Column(name = "nick_name") public String nick_name; public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } public String getNick_name() { return nick_name; } public void setNick_name(String nick_name) { this.nick_name = nick_name; }}
對類添加Table註解,對類的成員添加Column註解,因此,我們可以先看看這兩個註解的定義。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Table { public static final String DEFAULT_ID_NAME = "Id"; public String name(); public String id() default DEFAULT_ID_NAME;}
Table的定義如上,有兩個成員,分別是id和name,通常我們只需要設定name,id的名字為設定預設。這個name就是資料庫的表名,id為表中作為id欄位的名字。
Column的定義比較複雜,但我們可以想象其中一定有name成員,name就是表中的欄位名。
然後,ActiveAndroid用了一個TableInfo類儲存類和表的串連資訊。先來看看這個類
package com.activeandroid;/* * Copyright (C) 2010 Michael Pardo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */import java.lang.reflect.Field;import java.util.Collection;import java.util.Collections;import java.util.LinkedHashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;import android.text.TextUtils;import android.util.Log;import com.activeandroid.annotation.Column;import com.activeandroid.annotation.Table;import com.activeandroid.util.ReflectionUtils;public final class TableInfo { ////////////////////////////////////////////////////////////////////////////////////// // PRIVATE MEMBERS ////////////////////////////////////////////////////////////////////////////////////// private Class<? extends Model> mType; private String mTableName; private String mIdName = Table.DEFAULT_ID_NAME; private Map<Field, String> mColumnNames = new LinkedHashMap<Field, String>(); ////////////////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////////////////// public TableInfo(Class<? extends Model> type) { mType = type; final Table tableAnnotation = type.getAnnotation(Table.class); if (tableAnnotation != null) { mTableName = tableAnnotation.name(); mIdName = tableAnnotation.id(); } else { mTableName = type.getSimpleName(); } // Manually add the id column since it is not declared like the other columns. Field idField = getIdField(type); mColumnNames.put(idField, mIdName); List<Field> fields = new LinkedList<Field>(ReflectionUtils.getDeclaredColumnFields(type)); Collections.reverse(fields); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { final Column columnAnnotation = field.getAnnotation(Column.class); String columnName = columnAnnotation.name(); if (TextUtils.isEmpty(columnName)) { columnName = field.getName(); } mColumnNames.put(field, columnName); } } } ////////////////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////// public Class<? extends Model> getType() { return mType; } public String getTableName() { return mTableName; } public String getIdName() { return mIdName; } public Collection<Field> getFields() { return mColumnNames.keySet(); } public String getColumnName(Field field) { return mColumnNames.get(field); } private Field getIdField(Class<?> type) { if (type.equals(Model.class)) { try { return type.getDeclaredField("mId"); } catch (NoSuchFieldException e) { Log.e("Impossible!", e.toString()); } } else if (type.getSuperclass() != null) { return getIdField(type.getSuperclass()); } return null; }}
首先是成員變數
private Class<? extends Model> mType; private String mTableName; private String mIdName = Table.DEFAULT_ID_NAME; private Map<Field, String> mColumnNames = new LinkedHashMap<Field, String>();
mType:需要被儲存的類的類型;
mTableName:儲存的類的表名;
mIdName:儲存的類的表的id欄位名稱;
mColumnNames: 儲存的表中的欄位名與類中的成員的映射;
public TableInfo(Class<? extends Model> type) { mType = type; final Table tableAnnotation = type.getAnnotation(Table.class); if (tableAnnotation != null) { mTableName = tableAnnotation.name(); mIdName = tableAnnotation.id(); } else { mTableName = type.getSimpleName(); }
......
}
tableAnnotation儲存被儲存類的註解,並從註解中讀出表名和表id名,如果沒有註解,則預設類的簡名為表名。
public TableInfo(Class<? extends Model> type) { mType = type; ...... // Manually add the id column since it is not declared like the other columns. Field idField = getIdField(type); mColumnNames.put(idField, mIdName);
......
}
手動添加表的id名與類的id關係。看看getIdField方法:
private Field getIdField(Class<?> type) { if (type.equals(Model.class)) { try { return type.getDeclaredField("mId"); } catch (NoSuchFieldException e) { Log.e("Impossible!", e.toString()); } } else if (type.getSuperclass() != null) { return getIdField(type.getSuperclass()); } return null; }
一個遞迴,通過getSuperclass()尋找父類,一直到父類為Model,將其中mId成員返回。
public TableInfo(Class<? extends Model> type) { ...... List<Field> fields = new LinkedList<Field>(ReflectionUtils.getDeclaredColumnFields(type)); Collections.reverse(fields); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { final Column columnAnnotation = field.getAnnotation(Column.class); String columnName = columnAnnotation.name(); if (TextUtils.isEmpty(columnName)) { columnName = field.getName(); } mColumnNames.put(field, columnName); } } }
如上這段代碼,通過反射取出了要儲存類的所有標註的成員,並擷取它們的註解欄位名,如果沒有解注欄位名,則用成員名代替。最終將它們全部與成員本身一一映射放入mColumnNames中。
以上就是一個TableInfo的初始化過程。下一次將閱讀將所有已標註類成員取出的代碼。
Done!
讀ActiveAndroid源碼(一)