Android使用View.post()方法記憶體洩漏
最近開發中,使用 AsyncTask + ProgressDialog 顯示進度資訊,但在AsyncTask停止,Activity finish 後該Activity的例項始終不會被gc,多次執行程式後,會存在多個activity,造成記憶體洩漏。 下面詳細分析一下:
一份顯示進度條的測試程式碼:
- publicclass Main extends Activity {
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
- TextView tv = new TextView(this);
- tv.setText("Init State");
- setContentView(tv);
- tv.setOnClickListener(new OnClickListener() {
- @Override
- publicvoid onClick(View v) {
- showProgress(Main.this);
- }
-
});
- }
- publicvoid showProgress(final Activity activity) {
- new AsyncTask<Void, Void, Void>() {
- ProgressDialog progressDial;
- protectedvoid onPreExecute() {
- progressDial = new ProgressDialog(activity);
-
progressDial.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- progressDial.show();
- };
- @Override
- protected Void doInBackground(Void... params) {
- doSomeHeavyWork(progressDial);
- returnnull;
- }
- protectedvoid onPostExecute(Void result) {
- progressDial.dismiss();
- };
- }.execute();
- }
- void doSomeHeavyWork(ProgressDialog progress) {
- try {
- for (int i = 1; i <= 10; ++i) {
- progress.setProgress(i);
- Thread.sleep(1000);
- }
- } catch (Exception e) {
- }
- }
- }
上述程式碼發生記憶體洩漏的地方在 doSomeHeavyWork() 的 progress.setProgress(i); 部分;我們看一下setProgress()的實現,最終會呼叫ProgressBar 類的如下方法:
- privatesynchronizedvoid refreshProgress(int id, int progress, boolean fromUser) {
- if (mUiThreadId == Thread.currentThread().getId()) {
- doRefreshProgress(id, progress, fromUser, true);
- } else {
- RefreshProgressRunnable r;
- if (mRefreshProgressRunnable != null) {
- // Use cached RefreshProgressRunnable if available
- r = mRefreshProgressRunnable;
- // Uncache it
- mRefreshProgressRunnable = null;
- r.setup(id, progress, fromUser);
- } else {
- // Make a new one
- r = new RefreshProgressRunnable(id, progress, fromUser);
- }
- post(r);
- }
- }
- privateclass RefreshProgressRunnable implements Runnable {
- privateint mId;
- privateint mProgress;
- privateboolean mFromUser;
- RefreshProgressRunnable(int id, int progress, boolean fromUser) {
- mId = id;
- mProgress = progress;
- mFromUser = fromUser;
- }
- publicvoid run() {
- doRefreshProgress(mId, mProgress, mFromUser, true);
- // Put ourselves back in the cache when we are done
- mRefreshProgressRunnable = this;
- }
- publicvoid setup(int id, int progress, boolean fromUser) {
- mId = id;
- mProgress = progress;
- mFromUser = fromUser;
- }
- }
if 語句表明當呼叫的該方法的執行緒是UI執行緒時,則直接執行doRefreshProgress() 方法以重新整理介面;否則,建立一個RefreshProgressRunnable,並通過呼叫View.pos()方法將其插入到UI執行緒的訊息佇列中。 View.post()實現如下:
- publicboolean post(Runnable action) {
- Handler handler;
- AttachInfo attachInfo = mAttachInfo;
- if (attachInfo != null) {
- handler = attachInfo.mHandler;
- } else {
- // Assume that post will succeed later
- ViewRootImpl.getRunQueue().post(action);
- returntrue;
- }
- return handler.post(action);
- }
在post() 函式註釋中,明確寫著:This method can be invoked from outside of the UI thread only when this View is attached to a window.
當ProgressDialog還沒有attach到當前window時(ProgressDialog.show() 方法是非同步執行的),mAttachInfo 值為 null,故而執行 else語句,再看一下getRunQueue()和其post() 方法:
- staticfinal ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
- static RunQueue getRunQueue() {
- RunQueue rq = sRunQueues.get();
- if (rq != null) {
- return rq;
- }
- rq = new RunQueue();
- sRunQueues.set(rq);
- return rq;
- }
- ……
- staticfinalclass RunQueue {
-
privatefinal
相關推薦
Android使用View.post()方法記憶體洩漏
最近開發中,使用 AsyncTask + ProgressDialog 顯示進度資訊,但在AsyncTask停止,Activity finish 後該Activity的例項始終不會被gc,多次執行程式後,會存在多個activity,造成記憶體洩漏。 下面詳細分析一下:
記憶體洩漏-非UI執行緒使用View.post()方法
轉自: 最近開發中,使用 AsyncTask + ProgressDialog 顯示進度資訊,但在AsyncTask停止,Activity finish 後該Activity的例項始終不會被gc,多次執行程式後,會存在多個activity,造成記
Visual Studio中檢測記憶體洩漏的方法
Visual Studio中檢測記憶體洩漏的方法 #include <iostream> //可以定位到發生記憶體洩露 所在的檔案和具體那一行,用於檢測 malloc 分配的記憶體 #define _CRTDBG_MAP_ALLOC #include <s
android防記憶體洩漏與記憶體優化的方法整理
記憶體洩漏 一、單利洩漏 存在記憶體洩露問題的一些程式碼片段像下面這樣: public class Util { private Context mContext;  
iOS記憶體洩漏檢測方法
常見洩漏的點 Retain Cycle,Block強引用 NSTimer釋放不當 第三方提供方法造成的記憶體洩漏 CoreFoundation方式申請的記憶體,忘記釋放 1. Block引用記憶體洩漏問題: [cell setSelectTagCityBl
JavaScript中4種常見的記憶體洩漏及避免方法
垃圾回收演算法 常用垃圾回收演算法叫做**標記清除 (Mark-and-sweep) **,演算法由以下幾步組成: 1、垃圾回收器建立了一個“roots”列表。roots 通常是程式碼中全域性變數的引用。JavaScrip
Handler記憶體洩漏分析與解決方法
最近整理完Android中訊息機制的知識後,想到Handler記憶體洩漏相關的問題也可以順便整理一下,便有了這篇文章,也方便以後自己查閱 為什麼Handler會造成記憶體洩漏 下面是一段簡單的Handler使用 public class MainActivity extend
iOS 記憶體洩漏排查方法及原因分析
級別: ★★☆☆☆ 標籤:「iOS」「記憶體洩漏排查」「Leaks工具」 作者: MrLiuQ 審校: QiShare團隊 本文將從以下兩個層面解決iOS記憶體洩漏問題: 記憶體洩漏排查方法(工具) 記憶體洩漏原因分析(解決方案) 在正式開始前,我們
【Web效能測試】記憶體洩漏測試方法之chrome記憶體快照
首先明確一下我們測試的目的:客戶端瀏覽器的js記憶體是否存在洩漏,伺服器端的話可不是這麼測,防止使用者使用時瀏覽器卡頓或崩潰。 F12開啟開發者工具,選中Memory頁簽下的Heap snapshot。 每次我們記錄快照前都要點選那個小垃圾桶,清一下快取,因為我們測記憶體洩漏是看
排查記憶體洩漏最簡單和直觀的方法
記憶體洩漏無疑會嚴重影響使用者體驗,一些本應該廢棄的資源和物件無法被釋放,導致手機記憶體的浪費,app使用的卡頓,那麼如何排查記憶體洩漏呢? 當然,首先我門有google的官方文件可以參考: 排查記憶體洩漏官方文件 官方文件(二) 大部分部落格的方法
java記憶體洩漏的分析方法
這幾天,一直在為Java的“記憶體洩露”問題糾結。Java應用程式佔用的記憶體在不斷的、有規律的上漲,最終超過了監控閾值。福爾摩 斯不得不出手了! 記憶體溢位 out of memory,是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如
C++ 記憶體洩漏檢測1:微軟自帶的記憶體洩漏檢測方法
在程式總的包含標頭檔案中新增以下程式碼, #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #else #define DEBUG_CLIENTBLOCK
C++ 記憶體洩漏檢測方法
程式中通常包含著靜態儲存區和棧記憶體。靜態儲存區也就是靜態記憶體,是用來儲存區域性static物件、類static資料成員以及定義在任何函式之外的變數(全域性變數)。棧記憶體用來儲存定義在函式內的非static物件。分配在靜態或棧記憶體中的物件由編譯器自動建立
Android記憶體洩漏場景及解決方法
本文包括以下內容: 1. 記憶體洩漏原理 2. Android記憶體洩漏發生的情況 3. 檢測記憶體洩漏的工具、方法 4. 如何避免記憶體洩漏 更多Android面試相關請點選 - 四步準備Android面試 - Android開發概要 - 大疆提前批第一次電面
JavaScript記憶體洩漏的排查方法
概述 Google Chrome瀏覽器提供了非常強大的JS除錯工具,Heap Profiling便是其中一個。Heap Profiling可以記錄當前的堆記憶體(heap)快照,並生成物件的描述檔案,該描述檔案給出了當時JS執行所用到的所有物件,以及這些物
JS記憶體洩漏排查方法(Chrome Profiles)
一、概述 Google Chrome瀏覽器提供了非常強大的JS除錯工具,Heap Profiling便是其中一個。Heap Profiling可以記錄當前的堆記憶體(heap)快照,並生成物件的描述檔案,該描述檔案給出了當時JS執行所用到的所有物件,以及這些物件所佔用的記憶體大小、引用的層級關係等等。這些
iOS開發使用 runtime 方法中的 class_copyIvarList,class_copyMethodList 方法時導致記憶體洩漏問題
前段時間在做公司新專案的時候使用了 runtime 的 class_copyIvarList 方法來獲取類的所有屬性的時候,用 leaks 檢測,發現這裡出現了記憶體洩漏。後來查了一些資料發現 class_copyIvarList 返回的物件需要手動釋放。因
7.JNI 記憶體洩漏 處理 方法總結
在c++中new的物件,如果不返回java,必須用release掉,否則記憶體洩露。包括NewStringUTF,NewObject。如果返回java不必release,java會自己回收。 jstring jstr = env->NewStringUTF((*p).
記憶體洩漏的定義及解決方法(智慧指標)
記憶體洩漏是指由於疏忽或錯誤,程式沒有釋放掉不再使用記憶體的情況。記憶體洩漏並非指記憶體在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤,失去了堆該段記憶體的控制,因而造成了記憶體的浪費。 對於C++這種沒有垃圾回收機制的語言來說,主要關注兩種型別的記憶體洩漏:
簡單記憶體洩漏檢測方法
我的環境是: XP SP2 . VS2003 最近在一個專案中,程式退出後都出現記憶體洩漏: Detected memory leaks!Dumping objects ->{73} normal block at 0x009C2680, 292 bytes long.