編輯:關於Android編程
進入正題
* 快速入門
* 創建你的數據庫模型
* 保存數據到數據庫
* 查詢數據庫
* 類型序列化
* 使用content provider
* 模型遷移
* 預設數據庫
讓我們一起來進入ActiveAndroid的世界。首先你要做的就是下載ActiveAndroid庫,又或者是最新的穩定版ActiveAndroid jar文件。如果你下載的是庫(其實就是一個工程),你必須得先編譯成jar文件再使用。
現在你已經有了ActiveAndroid的庫,你可以把它添加到你的工程build path了。如果你使用的是eclipse:
1. 如果還沒有工程先創建一個Android工程
2. 把ActiveAndroid.jar復制到工程的libs目錄下
3. 右鍵點擊工程然後選擇Build Path -> Configure Build Path…
4. 點擊Add Ecternal Jars…,選中ActiveAndroid jar並確定
如果你使用的是AndroidStudio:
1. 創建一個工程(已經有了就不用再創建了)
2. 復制jar文件到libs目錄下
3. 右鍵點擊jar文件,選擇Add as a Library…
首先從Git上克隆源碼並且安裝到你本地倉庫
注意:需要使用Maven3.1.1以及以上的版本
1. git clone https://github.com/pardom/ActiveAndroid.git
2. cd ActiveAndroid
3. mvn clean install
工程創建成功後,添加依賴到pom.xml中
com.activeandroid
activeandroid
(insert latest version)
修改工程build.gradle,包含以下內容:
repositories {
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
現在你已經將ActiveAndroid添加到工程了,你可以兩步配置開始使用。首先需要添加一些全局設置。ActiveAndroid會在AndroidManifest.xml文件中查找這些設置。打開AndroidManifest.xml添加配置。
AA_DB_NAME(可選) AA_DB_VERSION(可選-默認為1)配置好的AndroidManifest.xml應該是這個樣子的
...
需要注意的是app的名字應該引用ActiveAndroid的Application類。ActiveAndroid工作必須設置這一步。如果你已經引用了一個自定義的Application類,只需要讓該類成為com.activeandroid.Application類的子類即可。
如果你正在使用自定義的Application類,只需要繼承把繼承android.app.Application類換成繼承com.activeandroid.Application就可以了。(這是原作者的話,感覺廢話真多)
public class MyApplication extends com.activeandroid.app.Application { ...
但是如果你已經繼承了其他庫的Application類,在Application類中做簡單的初始化就可以。調用ActiveAndroid.dispose();
public class MyApplication extends SomeLibraryApplication {
@Override
public void onCreate() {
super.onCreate();
ActiveAndroid.initialize(this);
}
}
如果你想動態創建一個數據庫,可以使用Configuration類。
public class MyApplication extends SomeLibraryApplication {
@Override
public void onCreate() {
super.onCreate();
Configuration dbConfiguration = new Configuration.Builder(this).setDatabaseName("xxx.db").create();
ActiveAndroid.initialize(dbConfiguration);
}
}
在我們的例子中有兩張表:Category和Item。
第二步你將會創建這些表的類,這同樣很簡單。
我們在下面設置數據庫模型的小節中再詳細介紹這個,下面是我們的類:
@Table(name = "Categories")
public class Category extends Model {
@Column(name = "Name")
public String name;
}
@Table(name = "Items")
public class Item extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Category")
public Category category;
}
創建數據庫非常簡單,只需要用你希望的表明作為類名創建類即可,需要給表的每一列對應的類成員加上注解。
有兩個重點:一是你的類必須繼承Model類,類成員必須使用@Column
來進行注解。
需要注意的是ActiveAndroid為表創建了id字段,該字段是自動遞增的主鍵。
ActiveAndroid使用了標准的構造器(指的是無參數的默認構造器)實例化對象,如果你定義了自己的構造器你必須另外定義一個無參數的構造器。
@Table(name = "Items")
public class Item extends Model {
// If name is omitted, then the field name is used.
@Column(name = "Name")
public String name;
@Column(name = "Category")
public Category category;
public Item() {
super();
}
public Item(String name, Category category) {
super();
this.name = name;
this.category = category;
}
}
在上面的小節中我們使用了Categories和Items的例子,Items屬於Categories而Categories有很多Items。我們怎麼在ActiveAndroid中表達這兩者的關系呢?
在Item類中我們可以直接通過創建一個Category類成員來表現兩者之間的關系。
@Table(name = "Items")
public class Item extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Category")
public Category category;
}
同樣的道理,Category類可以指示多個Items的關系。我們使用一個輔助方法來完成。
@Table(name = "Categories")
public class Category extends Model {
@Column(name = "Name")
public String name;
// This method is optional, does not affect the foreign key creation.
public List- items() {
return getMany(Item.class, "Category");
}
}
你可以通過在列定義的注解中加上index = true
來給指定的列設置索引。
@Column(name = "Name", index = true)
public String name;
@Column(name = "Category", index = true)
public String category;
ActiveAndroid會查找所有的文件來找出Model類,這個過程會非常緩慢,特別是當工程有很多依賴的時候。為了加快這個過程,在AndroidManifest文件中顯式指定Model類。
不要使用以下的詞來命名表和列:
ABORT DEFAULT INNER REGEXP
ACTION DEFERRABLE INSERT REINDEX
ADD DEFERRED INSTEAD RELEASE
AFTER DELETE INTERSECT RENAME
ALL DESC INTO REPLACE
ALTER DETACH IS RESTRICT
ANALYZE DISTINCT ISNULL RIGHT
AND DROP JOIN ROLLBACK
AS EACH KEY ROW
ASC ELSE LEFT SAVEPOINT
ATTACH END LIKE SELECT
AUTOINCREMENT ESCAPE LIMIT SET
BEFORE EXCEPT MATCH TABLE
BEGIN EXCLUSIVE NATURAL TEMP
BETWEEN EXISTS NO TEMPORARY
BY EXPLAIN NOT THEN
CASCADE FAIL NOTNULL TO
CASE FOR NULL TRANSACTION
CAST FOREIGN OF TRIGGER
CHECK FROM OFFSET UNION
COLLATE FULL ON UNIQUE
COLUMN GLOB OR UPDATE
COMMIT GROUP ORDER USING
CONFLICT HAVING OUTER VACUUM
CONSTRAINT IF PLAN VALUES
CREATE IGNORE PRAGMA VIEW
CROSS IMMEDIATE PRIMARY VIRTUAL
CURRENT_DATE IN QUERY WHEN
CURRENT_TIME INDEX RAISE WHERE
CURRENT_TIMESTAMP INDEXED RECURSIVE WITH
DATABASE INITIALLY REFERENCES WITHOUT
(其實就是一大波SQL裡的關鍵字)
如果你發現還有其他的,請告訴我。
現在你已經做好了數據庫模型,然後我們來看一下怎麼把記錄保存到數據庫。
為了保存一條新的記錄,只需要創建activeandroid.Model
類的一個實例,給其中的字段賦上值,然後調用.save()
方法。save方法用於插入和更新記錄。
下面是一個例子
Category restaurants = new Category();
restaurants.name = "Restaurants";
restaurants.save();
Item item = new Item();
item.category = restaurants;
item.name = "Outback Steakhouse";
item.save();
添加一些items
item = new Item();
item.category = restaurants;
item.name = "Red Robin";
item.save();
item = new Item();
item.category = restaurants;
item.name = "Olive Garden";
item.save();
為了同時插入多條記錄,你可以使用事務。在事務之間做插入操作可以提升速度。下面是一個例子:
ActiveAndroid.beginTransaction();
try {
for (int i = 0; i < 100; i++) {
Item item = new Item();
item.name = "Example " + i;
item.save();
}
ActiveAndroid.setTransactionSuccessful();
}
finally {
ActiveAndroid.endTransaction();
}
在事務之中執行大約耗時40毫秒,如果不寫在事務之間耗時大約4秒。
怎麼刪除記錄呢?刪除一條記錄只需要調用delete()
方法。下面的例子我們通過Id來load一個Item對象並且刪除它。
Item item = Item.load(Item.class, 1);
item.delete();
或者你可以靜態地刪除
Item.delete(Item.class, 1);
你還可以構建查詢語法來刪除
new Delete().from(Item.class).where("Id = ?", 1).execute();
在ActiveAndroid中所有的查詢操作都通過構建查詢的語句或者調用Model.method
。
這是目前我們完成了的:
@Table(name = "Items")
public class Item extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Category")
public Category category;
}
我們希望隨機得到一條記錄,增加一個方式來實現這個功能。
public static Item getRandom() {
return new Select()
.orderBy("RANDOM()")
.executeSingle();
}
在ActiveAndroid中創建一個查詢類似於創建一條普通的SQL語句。我們創建一個新的select對象,在Item類中完成查詢的功能。調用orderBy來做隨機。調用execute()
方法來執行查詢,或者像下面的例子使用executeSingle()
。
如果我們只是想從一個確定的category中查詢,我麼只需給方法的參數傳入值就可以了。方法如下:
public static Item getRandom(Category category) {
return new Select()
.from(Item.class)
.where("Category = ?", category.getId())
.orderBy("RANDOM()")
.executeSingle();
}
下面是通過一個category來獲取所有items,按照name屬性排序。
public static List- getAll(Category category) {
return new Select()
.from(Item.class)
.where("Category = ?", category.getId())
.orderBy("Name ASC")
.execute();
}
ActiveAndroid可以處理默認的數據類型,如果需要處理自定義類型,可以使用TypeSerializer類來做到。最好的學習方法就是通過例子,下面以Date類型舉例。
當我們創建一個TypeSerializer類型時我們必須想辦法把自定義的類型轉換為基本數據類型讓ActiveAndroid來處理。Date類型可以轉換為Long型,這樣我們就可以使用了。
下面是例子。
final public class UtilDateSerializer extends TypeSerializer {
@Override
public Class getDeserializedType() {
return Date.class;
}
@Override
public Class getSerializedType() {
return Long.class;
}
@Override
public Long serialize(Object data) {
if (data == null) {
return null;
}
return ((Date) data).getTime();
}
@Override
public Date deserialize(Object data) {
if (data == null) {
return null;
}
return new Date((Long) data);
}
}
第一個方法getDeserializedType返回我們進行序列化的的class,對於Date類型我們就返回Date.class。
第二個方法返回相反的類型,也就是我們希望把Date類型保存時所用的類型(這裡就是Long型)。我們使用枚舉類型來代替字符串類型。下面是這個方法的枚舉類。(這一句翻譯得可能不准確,因為我也不知道下面的枚舉類有什麼作用,看懂的童鞋請告訴我)
public enum SQLiteType {
INTEGER, REAL, TEXT, BLOB
}
再下一個方法就是把我們自定義的類型轉換為ActiveAndroid可以保存的類型,這裡使用了getTime()
方法返回了一個Long型對象。
最後一個方法是把保存在數據庫的數據轉換為自定義類型,Date類型可以使用Long型來構對象,所以我們使用一個Long來生成一個Date對象。
最後在AndroidManifest.xml中注冊我們自定義的類型。
注意:你必須先寫明指定列作為id列詳見https://github.com/pardom/ActiveAndroid/pull/132才能使用
mySpinner.setAdapter(new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_expandable_list_item_1,
null,
new String[] { "MyProperty" },
new int[] { android.R.id.text1 },
0));
getActivity().getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks() {
@Override
public Loader onCreateLoader(int arg0, Bundle cursor) {
return new CursorLoader(getActivity(),
ContentProvider.createUri(MyEntityClass.class, null),null, null, null, null);
}
@Override
public void onLoadFinished(Loader arg0, Cursor cursor) {
((SimpleCursorAdapter)mySpinner.getAdapter()).swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader arg0) {
((SimpleCursorAdapter)mySpinner.getAdapter()).swapCursor(null);
}
});
還需要在AndroidManifest.xml中注冊
...
當數據庫版本通過Configuration或者AA_DB_VERSION來設計時,如果添加了新的類,ActiveAndroid會自動把對應的表添加到數據庫中。如果你想修改已經存在的表(比如添加一列或者重命名表名),都可以通過
腳本來完成。新的版本號就是AndroidManifest.xml中的AA_DB_VERSION的值,腳本文件需要存放於assets/migrations
如果腳本的文件名比舊的數據庫版本號大ActiveAndroid會執行該腳本,小於或等於即不會執行。
比如給Items
表添加一個color
列,需要把AA_DB_VERSION修改為2並且添加2.sql,該腳本文件如下:
ALTER TABLE Items ADD COLUMN color INTEGER;
更多關於ALTER TABLE
的用法可以參考SQLite docs
可以按照以下步驟來使用已經填充好數據的數據庫:
1. 在assets
目錄下放置SQLite數據庫文件,比如:
/myapp/src/main/assets/prepop.db
2. 確保在manifest文件中設置了AA_DB_NAME
,例如:
這樣當你安裝好應用程序prepop.db
就會復制到/data/data/myapp/databases
目錄下了
注意:這樣會存在兩個數據庫,一份打包到APK中,另一份在/data/data/myapp/databases
中
為了確保這一點,請注意以下兩點:
1. 設置android_metadata
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US')
INSERT INTO "android_metadata" VALUES ('en_US')
如果在模型類中未定義id
列,確保主鍵被命名為Id
而不是Android數據庫默認的_id
。但是,如果你的數據庫是放到ListView中顯示的,建議把主鍵列設為_id
。可以在@Table
注解中寫上id = "_id"
:
@Table(name = "Items", id = "_id")
public class Item extends Model {
以上就是ActiveAndroid的使用方法,這裡只是給出了一些最常見的用法,本人的英語水平也有限,有翻譯得不准或者不好的地方請告訴我。當然,如果你的英語水平足夠好,我還是希望你能看原文:我是Github項目地址,我是文檔地址。
這是在了解下拉刷新功能原理下的產物,下拉刷新可以說是國產APP裡面必有的功能,連Google都為此出了SwipeRefreshLayout,一種MD風格的下拉刷新。 不過
本次博客主要介紹一個天氣效果的實現過程最近公司的項目加入天氣模塊,需要實現下面的效果: 然後根據自己的構想實現了下面的效果: 下面會詳
android是因為我的興趣而自學的,當初學完java se感覺迫切需要實現下自己的技能,然後看到身邊的手機,就決定學下android編個app玩下。現在斷斷續續倒騰了兩
微博開發遇到很多bug 總結一下 我遇到BUG (1) :sso package or singn error 出現這個問題 是我沒有在 博客中填寫正確的包