android之Loaders初步

Loaders 是android 3.0新引入的api和接口。它具有以下特點:

1.     Loaders用於所有的Activity和Fragment;

2.     提供異步數據裝載機制;

3.     監控他們的來源數據變化情況,在數據發生變化的時候傳遞新的結果;

4.     自動重連到最後一個數據加載器遊標,因此不需要重新查詢數據。

從以上特點感覺可以很方便的異步獲取數據。想一下handler和asyTask吧。上面的描述好像很美好。

Lorders API主要包括以下接口和類。

LoaderManager:管理着一個Activity或者Fragment中的一個或多個Loader實例,每個Activity或者Fragment只有對應一個LoaserManager。

LoaderManager.LoaderCallbacks.一個回調接口,需要自己實現,接口定義了一些初始化的方法和取得數據後的回調方法。

Loader:一個抽象類,負責異步加載數據。

AsyncTaskLoader:繼承Loader,使用asyTask來加載數據。

CursorLoader:AsyncTaskLoader的子類。可以用來查詢ContentResolver,並返回一個Cursor。

 

故從以上看出,使用CursorLoader可以很方便的異步獲取數據並堅持其變化,當然這侷限於ContentResolver,不過這可以用到很多android的原生數據了,如聯繫人、圖片等。

 

如下的一個例子來自android官方文檔,簡單的說明了如何使用CursorLoader。

 

import android.app.ListFragment;

import android.app.LoaderManager.LoaderCallbacks;

import android.content.CursorLoader;

import android.content.Loader;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.provider.ContactsContract.Contacts;

import android.text.TextUtils;

import android.util.Log;

import android.view.Menu;

import android.view.MenuInflater;

import android.view.MenuItem;

import android.view.View;

import android.widget.ListView;

import android.widget.SearchView;

import android.widget.SearchView.OnQueryTextListener;

import android.widget.SimpleCursorAdapter;

 

public  class CursorLoaderListFragment extends ListFragment

 

implements OnQueryTextListener, LoaderCallbacks<Cursor> {

 

 

 

// This is the Adapter being used to display the list's data.

 

SimpleCursorAdapter mAdapter;

 

 

 

// If non-null, this is the current filter the user has provided.

 

String mCurFilter;

 

 

 

@Override public void onActivityCreated(Bundle savedInstanceState) {

 

super.onActivityCreated(savedInstanceState);

 

 

 

// Give some text to display if there is no data.  In a real

 

// application this would come from a resource.

 

setEmptyText("No phone numbers");

 

 

 

// We have a menu item to show in action bar.

 

setHasOptionsMenu(true);

 

 

 

// Create an empty adapter we will use to display the loaded data.

 

mAdapter = new SimpleCursorAdapter(getActivity(),

 

        android.R.layout.simple_list_item_2, null,

 

        new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },

 

        new int[] { android.R.id.text1, android.R.id.text2 }, 0);

 

setListAdapter(mAdapter);

 

 

 

// Prepare the loader.  Either re-connect with an existing one,

 

// or start a new one.

 

getLoaderManager().initLoader(0, null, this);

 

}

 

 

 

@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

 

// Place an action bar item for searching.

 

MenuItem item = menu.add("Search");

 

item.setIcon(android.R.drawable.ic_menu_search);

 

item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

 

SearchView sv = new SearchView(getActivity());

 

sv.setOnQueryTextListener(this);

 

item.setActionView(sv);

 

}

 

 

 

public boolean onQueryTextChange(String newText) {

 

// Called when the action bar search text has changed.  Update

 

// the search filter, and restart the loader to do a new query

 

// with this filter.

 

mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;

 

getLoaderManager().restartLoader(0, null, this);

 

return true;

 

}

 

 

 

@Override public boolean onQueryTextSubmit(String query) {

 

// Don't care about this.

 

return true;

 

}

 

 

 

@Override public void onListItemClick(ListView l, View v, int position, long id) {

 

// Insert desired behavior here.

 

Log.i("FragmentComplexList", "Item clicked: " + id);

 

}

 

 

 

// These are the Contacts rows that we will retrieve.

 

static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {

 

Contacts._ID,

 

Contacts.DISPLAY_NAME,

 

Contacts.CONTACT_STATUS,

 

Contacts.CONTACT_PRESENCE,

 

Contacts.PHOTO_ID,

 

Contacts.LOOKUP_KEY,

 

};

 

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

 

// This is called when a new Loader needs to be created.  This

 

// sample only has one Loader, so we don't care about the ID.

 

// First, pick the base URI to use depending on whether we are

 

// currently filtering.

 

Uri baseUri;

 

if (mCurFilter != null) {

 

    baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,

 

            Uri.encode(mCurFilter));

 

} else {

 

    baseUri = Contacts.CONTENT_URI;

 

}

 

 

 

// Now create and return a CursorLoader that will take care of

 

// creating a Cursor for the data being displayed.

 

String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("

 

        + Contacts.HAS_PHONE_NUMBER + "=1) AND ("

 

        + Contacts.DISPLAY_NAME + " != '' ))";

 

return new CursorLoader(getActivity(), baseUri,

 

        CONTACTS_SUMMARY_PROJECTION, select, null,

 

        Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");

 

}

 

 

 

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

 

// Swap the new cursor in.  (The framework will take care of closing the

 

// old cursor once we return.)

 

mAdapter.swapCursor(data);

 

}

 

 

 

public void onLoaderReset(Loader<Cursor> loader) {

 

// This is called when the last Cursor provided to onLoadFinished()

 

// above is about to be closed.  We need to make sure we are no

 

// longer using it.

 

mAdapter.swapCursor(null);

 

}}

 

 

Loader可以自動的監控數據源的變化,這無疑是一個亮點。這點在CursorLoader中表現的淋漓盡致。但是在對於實際應用來說,數據源很可能來自Internet,當然不可能是Cursor。(你當然可以自己取數據,然後存起來如db中,然後轉化爲cursor)。這時就需要用AsyncTaskLoader,但是它是一個抽象類,所以需要自己實現,你需要自己實現它的監控數據變化機制,這絕不是一個簡單的問題。而Loaders從這點來說就是定義了一系列的接口框架,需要自己實現這些機制。例子見

http://developer.android.com/reference/android/content/AsyncTaskLoader.html

發佈了35 篇原創文章 · 獲贊 18 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章