編輯:關於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 ArrayListmManagedCursors = 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()方法。
ScrollView添加提示Arrow(箭頭) 在ScrollView的滑動功能中,需要給用戶提示,可以滑動,可以添加兩個箭頭。
支付寶的快捷支付Android版業務流程比較麻煩,出現的意外情況比較多.在此,簡單說下開發流程以及出現錯誤的解決方案; 1.注冊支付業務.這裡不在贅述.建立數據安全傳輸所
本文在實現雪花效果的基礎上,根據漫天飛舞雪花,實現下雨天場景的效果,使用eclipse android 版本,具體內容如下雪花效果圖:具體代碼:1、漫天飛舞的雪花主要代碼
public class EngineerJspActivity extends Activity { private static String Tag = &q