編輯:關於Android編程
新手在使用數據庫的時候,很容易忘記關閉Cursor,造成嚴重內存洩漏。有什麼好的方法解決這個問題呢?除了自己管理Cursor,有什麼辦法把Cursor交給系統管理,而不需要自己主動close呢?manageQuery可以為你維護這個cursor。在你退出activity時為你自動關閉。
The method managedQuery(Uri, String[], String, String[], String) from the type Activity is deprecated。
android官方文檔推薦用CursorLoader類來取代。
我們先來分析一下manageQuery是如何管理cursror的
private static final class ManagedCursor {
ManagedCursor(Cursor cursor) {
mCursor = cursor;
mReleased = false;
mUpdated = false;
}
private final Cursor mCursor;
private boolean mReleased;
private boolean mUpdated;
}
private final ArrayList mManagedCursors =
new ArrayList();
public final Cursor managedQuery(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
if (c != null) {
startManagingCursor(c);
}
return c;
}
public void startManagingCursor(Cursor c) {
synchronized (mManagedCursors) {
mManagedCursors.add(new ManagedCursor(c));
}
}
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final ManagedDialog md = mManagedDialogs.valueAt(i);
if (md.mDialog.isShowing()) {
md.mDialog.dismiss();
}
}
mManagedDialogs = null;
}
// close any cursors we are managing.
synchronized (mManagedCursors) {
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
mManagedCursors.clear();
}
// Close any open search dialog
if (mSearchManager != null) {
mSearchManager.stopSearch();
}
getApplication().dispatchActivityDestroyed(this);
}
看來這幾個方法就已經非常明確了。將cursor封裝之後放到一個ArrayList中,在Activity的Destroy方法中關閉cursor,Activity正常銷毀一定會走OnDestroy()方法的,這樣可以保證cursor會被關閉。
LoaderManager方法有下面幾個方面更勝一籌:
1. startManagingCursor管理Cursors,而LoaderManager管理Loader對象。Loader是一個模板類,D是一個包含了需要載入數據的類。也就是說,數據源並不必須是Cursor,它可以是List、JSONArray。。。任何類。LoaderManager與它包含的數據內容解耦了,所以更加靈活。
2. 調用startManagingCursor會導致Activity在已經加入管理的Cursor上調用requery()方法。在第一篇文章中提到過,在UI線程執行requery()方法代價非常高。相反的是,Loader的子類會異步載入(譯者注:另外再開一個線程,就叫異步了。)數據,所以使用LoaderManager永遠不會產生阻塞UI線程的情況。
3. startManagingCursor在配置變化(例如橫豎屏切換)時,並不會保持Cursor的狀態。麻煩的是,每次Activity由於配置變化(比如,簡單的橫豎屏切換),都會導致Cursor下回並且被重新查詢。LoaderManager就智能多了,當配置變化時,它會保持它裡面的Loader們的狀態,所以並不需要重新查詢數據。
4. LoaderManager提供無縫的數據監測。任何時候,當Loader的數據源改變,LoaderManager將會從對應的Loader上面接收到一個新的同步載入數據,並將更新數據返回給客戶端(注意:僅當Loader被正確實現,LoaderManager才會接收到這些數據變化通知。我們將會在該系列的第三篇文章討論自定義Loaders的實現)。
CursorLoader使用LoaderManager管理Cursor
使用方法如下
LoaderCallbackscallback= new LoaderCallbacks () { @Override public Loader onCreateLoader(int id, Bundle args) { // 返回自己需要的CursorLoader return null ; } @Override public void onLoadFinished(Loader loader, Cursor data) { // 使用swapCursor()方法,以使舊的游標不被關閉. simpleCursorAdapter.swapCursor(cursor); } @Override public void onLoaderReset(Loader loader) { 、 // 一般寫這樣寫 simpleCursorAdapter.swapCursor(null); } }; getLoaderManager().initLoader(0, null, callback);
需要注意的是當使用initLoader()時,如果指定ID的裝載器已經存在,則它使用這個裝載器.如果不存在呢,它將創建一個新的.但是有時你卻是想丟棄舊的然後開始新的數據,要使用restartLoader()方法。
Android - ScrollView添加提示Arrow(箭頭)
ScrollView添加提示Arrow(箭頭) 在ScrollView的滑動功能中,需要給用戶提示,可以滑動,可以添加兩個箭頭。
Android-支付寶快捷支付
支付寶的快捷支付Android版業務流程比較麻煩,出現的意外情況比較多.在此,簡單說下開發流程以及出現錯誤的解決方案; 1.注冊支付業務.這裡不在贅述.建立數據安全傳輸所
Android營造雪花和雨滴浪漫效果
本文在實現雪花效果的基礎上,根據漫天飛舞雪花,實現下雨天場景的效果,使用eclipse android 版本,具體內容如下雪花效果圖:具體代碼:1、漫天飛舞的雪花主要代碼
Android 面試之橫豎屏切換的Activity生命周期
public class EngineerJspActivity extends Activity { private static String Tag = &q