天天看點

Android之資料存儲----使用LoaderManager異步加載資料庫

一、各種概念:

1、loaders:

适用于android3.0以及更高的版本,它提供了一套在ui的主線程中異步加載資料的架構。使用loaders可以非常簡單的在activity或者fragment中異步加載資料,一般适用于大量的資料查詢,或者需要經常修改并及時展示的資料顯示到ui上,這樣可以避免查詢資料的時候,造成ui主線程的卡頓。

即使是查詢sqlite資料庫,用loaders來操作會更加的簡便。

loaders有以下特點:

可以适用于activity和fragment。

可以提供異步的方式加載資料。

監聽資料源,當資料改變的時候,将新的資料釋出到ui上。

loaders使用cursor加載資料,在更改cursor的時候,會自動重新連接配接到最後配置的cursor中讀取資料,是以不需要重新查詢資料。

在android中使用loaders機制,需要多個類和接口的配合,以下是它們大緻的關系圖,之後的内容會對這幾個類或接口進行詳細講解:

2、loadermanager

用于在activity或者fragment中管理一個或多個loader執行個體。在activity或者fragment中,可以通過getloadermanager()方法擷取loadermanager對象,它是一個單例模式。

介紹幾個loadermanager提供的方法,用于管理loader:

loader<d> initloader(int id,bundle bundle,loadercallbacks<d> callback):初始化一個loader,并注冊回調事件。

loader<d> restartloader(int id,bundle bundle,loadercallbacks<d> callback):重新啟動或建立一個loader,并注冊回調事件。

loader<d> getloader(int id):傳回給定id的loader,如果沒有找到則傳回null。

void destroyloader(int id):根據指定id,停止和删除loader。

通過上面幾個方法的參數可以看到,都有一個id參數,這個id是loader的辨別,因為loadermanager可以管理一個或多個loader,是以必須通過這個id參數來唯一确定一個loader。而initloader()、restartloader()中的bundle參數,傳遞一個bundle對象給loadercallbacks中的oncreateloader()去擷取,下面介紹loadercallbacks。

3、loadermanager.loadercallbacks

loadercallbacks是loadermanager和loader之間的回調接口。它是一個回調接口,是以我們需要實作其定義的三個方法:

loader<d> oncreateloader(int id,bundle bundle):根據指定id,初始化一個新的loader,并傳回。

void onloadfinished(loader<d> loader,d data):當loader被加載完畢後被調用,在其中處理loader擷取的cursor資料。

void onloaderreset(loader<d> loader):當loader被銷毀的時候被調用,在其中可以使loader的資料不可用。

從loadercallbacks的聲明的幾個方法中可以看到,它是一個泛型的接口,需要指定loader資料的類型。如果是資料源是從一個contentprovider中擷取的,一般直接使用它的子類cursorloader,下面介紹cursorloader。

4、cursorloader

我們知道,loader一個抽象的類,用于執行異步加載資料,這個loader對象可以監視資料源的改變和在内容改變後,以新資料的内容改變ui的展示。它是一個抽象接口,所有需要實作的loader功能的類都需要實作這個接口,但是如果需要自己開發一個裝載機的話,一般并不推薦繼承loader接口,而是繼承它的子類asynctaskloader,這是一個以asynctask架構執行的異步加載。

android中還提供了一個cursorloader類,它是asynctaskloader的子類,一個異步的加載資料的類,通過contentresolver的标準查詢并傳回一個cursor。這個類實作了loader的協定,以一種标準的方式查詢cursor。

cursorloader類有兩個構造函數,推薦使用第二個,因為使用第一個構造函數,需要還需要通過cursorloader提供的一些了getxxx()方法設定對應的屬性。兩個構造方法如下:

cursorloader(context context)

cursorloader(context context,uri uri,string[] projection,string selection ,string[] selectionargs,string sortorder)

二、代碼舉例:

在這個例子中,資料使用sqlite資料庫儲存,然後用contentprovider進行資料的請求與通路。在sqlite資料庫中,已經存在一個student表,它有兩個字段:_id,name。在本例中,使用一個listview展示資料,使用loadermanager管理一個loader,并通過這個loader的回調接口進行加載listview的資料顯示并實時重新整理,最終進行完成對sqlite資料庫中的資料進行增加與删除。

整個工程檔案的目錄結構如下:

Android之資料存儲----使用LoaderManager異步加載資料庫

具體步驟如下:

步驟(1):建立類persondao,用于進行對sqlite的crud操作

步驟(2):建立類dbhelper,用于初始化sqliate資料庫

步驟(3):建立類personcontentprovider,繼承contetprovider,記得聲明權限。

步驟(4):添加單元測試類。我們在單元測試裡向sqlite中添加一些記錄。

我們在步驟(4)的單元測試裡向資料庫中添加一些資料之後,可以開始接下來最關鍵的步驟了:

步驟(5):

mainactivity.java:

Android之資料存儲----使用LoaderManager異步加載資料庫
Android之資料存儲----使用LoaderManager異步加載資料庫

核心代碼:132行至162行、95行和122行的實時重新整理

注意為listview綁定擴充卡的代碼:listview.setadapter(madapter)是在loader的回調接口中(132行)進行的,也就是在這裡更新ui,這樣就能夠實作自動重新整理ui。

43行:建立一個simplecursoradapter擴充卡

先通過getloadermanager()方法擷取loadermanager對象(48行),然後通過manager.initloader(1000, null, callbacks)初始化一個loader(50行)。其方法的完整版是:

<code>public abstract &lt;d&gt; loader&lt;d&gt; initloader(int id,bundle args, loadermanager.loadercallbacks&lt;d&gt; callback)</code>

第一個參數id:一個acticity中可以加載多個loader,是以要給每個loader制定一個唯一的辨別符id。第二個參數可以置空。

第三個參數callback:回調。

loader的回調接口是在132行至162行定義的,也就是在這裡異步加載資料庫的内容,顯示在listview上,同時能夠自動更新。

我們在第53行為listview注冊一個上下文菜單,上下文的菜單布局是在62行的r.menu.contentmenu.xml中定義的(稍後給出代碼)。

當使用者單擊單個的item時,彈出菜單選項,讓你選擇是添加還是删除(67行定義的方法)。如果是選擇添加内容,則彈出一個對話框(71行)(對話框的布局檔案r.layout.add_name稍後給出),輸入需要加入的内容,單擊确定,就會更新到ui(95行的manager.restartloader(1000, null, callbacks)方法);如果選擇删除内容,則直接删除,并更新ui(122行的manager.restartloader(1000, null, callbacks)方法)。

r.menu.contentmenu.xml:用于定義上下文菜單的布局

Android之資料存儲----使用LoaderManager異步加載資料庫
Android之資料存儲----使用LoaderManager異步加載資料庫

r.layout.add_name.xml:定義添加内容的布局

Android之資料存儲----使用LoaderManager異步加載資料庫
Android之資料存儲----使用LoaderManager異步加載資料庫

布局效果如下:

Android之資料存儲----使用LoaderManager異步加載資料庫

運作程式,動态示範效果如下:

Android之資料存儲----使用LoaderManager異步加載資料庫

圖文分解如下:

初始界面為:

Android之資料存儲----使用LoaderManager異步加載資料庫

單擊長按第二個item,會彈出一個菜單:

Android之資料存儲----使用LoaderManager異步加載資料庫

如果我們選擇上圖菜單中的“添加”,會彈出一個對話框:

Android之資料存儲----使用LoaderManager異步加載資料庫

我們在上面的對話框中輸入smyhvae,點選“确定”,就會将内容添加到listview中,并自動更新ui:

Android之資料存儲----使用LoaderManager異步加載資料庫

如果單擊菜單中的“删除”,會直接删除。

注:本文采用的擴充卡是simplecursoradapter,可以參考老羅的老版視訊,采用的是自定義擴充卡baseadapter。