1. 程式人生 > >Handler的正確使用,使用靜態內部類+弱引用,解決記憶體洩漏,舉例說明在使用ProgressBar時的Handler類的靜態內部類實現。

Handler的正確使用,使用靜態內部類+弱引用,解決記憶體洩漏,舉例說明在使用ProgressBar時的Handler類的靜態內部類實現。

       在Android中使用ProgressBar進行回撥設定進度時候會提示‘This Handler class should be static or leaks might occur’的警告,那就說明是你的自定義Handler類有記憶體洩露的問題,一般來說就是持有外部類的引用。要解決這個ProgressBar的使用問題需要明確如下幾個知識點:

1.Android的UI(比如ProgressBar)也是執行緒不安全的,如果想要更新應用程式裡的UI元素,則必須在主執行緒中進行,否則會出現異常。

2.不能在UI主執行緒中使用Thread.sleep();會導致檢視變化看不到(後面做ProgressBar演示需要用到)。

3.靜態內部類是不持有外部類的引用,因此自定義Handler類可以用靜態內部類來完成,至於為什麼不持有外部類的引用可參考:

4.如果你想在靜態內部類/匿名類中使用外部類的屬性或方法時,可以顯示的持有一個弱引用(WeakReference )。

  • 強引用:Java中裡面最廣泛的使用的一種,也是物件預設的引用型別,如果又一個物件具有強引用,那麼垃圾回收器是不會對它進行回收操作的,當記憶體的空間不足的時候,Java虛擬機器將會拋OutOfMemoryError錯誤,這時應用將會被終止執行
  • 軟引用:一個物件如果只有一個軟引用,那麼當記憶體空間充足是,垃圾回收器不會對他進行回收操作,只有當記憶體空間不足的時候,這個物件才會被回收,軟引用可以用來實現記憶體敏感的快取記憶體,如果配合引用佇列(ReferenceQueue使用,當軟引用指向物件被垃圾回收器回收後,java會把這個軟引用加入到與之關聯的引用佇列中)
  • 弱引用:弱引用是比軟引用更弱的一種的引用的型別,只有弱引用指向的物件的生命週期更短,當垃圾回收器掃描到只有具有弱引用的物件的時候,不敢當前空間是否不足,都會對弱引用物件進行回收,當然弱引用也可以和一個佇列配合著使用
  • 引用佇列:ReferenceQueue一般是作為WeakReference SoftReference 的構造的函式引數傳入的,在WeakReference 或者是 softReference 的指向的物件被垃圾回收後,ReferenceQueue就是用來儲存這個已經被回收的Reference

下面給大家展示用靜態內部類實現Handler類來完成ProgressBar的進度條顯示的原始碼。

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
   
    private ProgressBar progressBar;
    
    private MyHandler handler = new MyHandler(this);
    
    /**
     * 靜態內部類實現Handler
     */
  
    private static class MyHandler extends Handler{

        private  WeakReference<MainActivity> mActivity;

        private MyHandler(MainActivity mActivity) {
            super();
            this.mActivity = new WeakReference<MainActivity>(mActivity);
        }

        @Override
        public void handleMessage(Message msg) {
            if(mActivity.get() == null){
                return;
            }

            //在靜態內部類/匿名類中使用外部類的屬性或方法時,可以顯示的持有一個弱引用
            final MainActivity activity = mActivity.get(); //弱引用
            activity.progress.setText(msg.arg1+"%");
                
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        progressBar = findViewById(R.id.progress_bar); //例項化ProgressBar
       
        Button button = findViewById(R.id.button);
       
         button.setOnClickListener(this); //啟動進度條的按鈕新增點選事件
        
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.button){
            new Thread(new Runnable() {
                @Override
                public void run() {
                   int progress = progressBar.getProgress();
                   while (progress < 100) {
                       try {
                         
                           Message message = new Message();
                           progress = progress + 1;
                           progressBar.setProgress(progress);
                           message.arg1 = progress;
                           handler.sendMessage(message);
                           Thread.sleep(100); //不能在主執行緒中使用
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                   }
                }
            }).start();
         
        }
   }
}

當然只是針對ProgressBar的顯示而又不想發生‘This Handler class should be static or leaks might occur’我們還可以使用Android提供的runOnUiThread來完成。原始碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
   
    private ProgressBar progressBar;

    private int pro;   //進度條的值
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        progressBar = findViewById(R.id.progress_bar); //例項化ProgressBar
       
        Button button = findViewById(R.id.button);
       
         button.setOnClickListener(this); //啟動進度條的按鈕新增點選事件
        
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.button){
            pro = progressBar.getProgress();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (pro <= 100) {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            runOnUiThread(new Runnable() {//切換回主執行緒更改ProgressBar的值
                                @Override
                                public void run() {
                                      progress.setText(String.format("%d%%", pro));
                                    
                                    }
                                    pro = pro + 1;
                                }
                            });
                        }
                    }
                }).start();
        }
   }
}

小弟也是最近再跟著郭霖大牛的《第一行程式碼》在學習android,純純的菜鳥一枚,對很多東西的認識不深,知其然不知其所以然,這也是我的第一篇博文,寫的不好,有錯誤的地方希望各位大神包含和指正,小弟感激不盡!

相關推薦

Handler正確使用,使用靜態部類+引用,解決記憶體洩漏舉例說明在使用ProgressBarHandler靜態部類實現

       在Android中使用ProgressBar進行回撥設定進度時候會提示‘This Handler class should be static or leaks might occur’的警告,那就說明是你的自定義Handler類有記憶體洩露的問題,一般來說就是

WeakReference 在android中的應用 引用防止記憶體洩漏

首先我們來看一段程式碼 public classAutoActivityextendsActivity{ Handler handler = new Handler(){ publicvoidhandleMessage(android.os.Message msg)

分析ThreadLocal的引用記憶體洩漏問題

目錄 一.介紹 二.問題提出   2.1記憶體原理圖   2.2幾個問題 三.回答問題   3.1為什麼會出現記憶體洩漏   3.2若Entry使用弱引用   3.3弱引用配合自動回收 四.總結         一.介紹   之前使用ThreadLocal的時候,就聽過Threa

匿名部類持外部引用造成記憶體洩漏問題

public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override publi

Handler還需要用到引用(WeakReference)嗎?

網上很多文章都說寫Hanlder,需要用static宣告為靜態的,還需要用弱引用包裹建構函式傳來的Activity例項。 比如這篇英文部落格 http://www.androiddesignpatterns.com/2013/01/inner-class-handler-

[轉]Android 如何有效的解決記憶體洩漏的問題 Android 如何有效的解決記憶體洩漏的問題

Android 如何有效的解決記憶體洩漏的問題   前言:最近在研究Handler的知識,其中涉及到一個問題,如何避免Handler帶來的記憶體溢位問題。在網上找了很多資料,有很多都是互相抄的,沒有實際的作用。 本文的記憶體洩漏檢測工具是:LeakCanary &nbs

解決記憶體洩漏

一:寫p層的方法 //解耦 public void datach(){ if (shopView != null){ shopView = null; } } 二:主頁面的方法 @Override public void onDestroy() {

Android 如何有效的解決記憶體洩漏的問題

前言:最近在研究Handler的知識,其中涉及到一個問題,如何避免Handler帶來的記憶體溢位問題。在網上找了很多資料,有很多都是互相抄的,沒有實際的作用。 本文的記憶體洩漏檢測工具是:LeakCanary  github地址:https://github.com/square/le

mvp銷燬,解決記憶體洩漏

mvp銷燬,解決記憶體洩漏 //model層銷燬執行緒 public void onDestory() { if (handler != null) { handler.removeCallbacksAndMessages(null); handler = null; } } //p

Android AsyncTask 取消全部任務 , 解決記憶體洩漏問題

以下程式碼具備的功能:  1. 取消當前新增的所有 AsyncTask , 儘量減少重複的網路請求任務 (場景: 我們需要在一個介面中定時每 10s 請求一次網路獲取一次資料 ,我們知道網路請求時間是不固定的 ,可能很快的請求完成,也可能很慢,因此,我為了儘量節省開銷

_064_Android_Android 如何有效的解決記憶體洩漏的問題

轉自https://www.cnblogs.com/zhaoyanjun/p/5981386.html,感謝作者的無私分享。  Android 如何有效的解決記憶體洩漏的問題 如何避免Handler帶來的記憶體溢位問題。 本文的記憶體洩漏檢測工具是:LeakCanary &nb

iOS NSString 記憶體洩漏 解決

遞迴, autorelease物件如何避免記憶體洩漏???? -(NSString *) getStuJsonString : (StuNode *) stuNode{     NSString *nodeJsonString = [[NSString alloc] i

Jboss—java.lang.OutOfMemoryError:Metaspace (解決記憶體溢位擴大記憶體

講一講故事開頭吧,小菜自己覺得非常重要! 今天Jenkins構建專案後端成功,可怕的是到了伺服器上部署時就失敗了。開始拍錯,先是懷疑Jenkins在搗亂呢,因此在本地打包釋出,非常順利的成功了。把這個war包拿到伺服器上去部署,竟然失敗!排除Jenkins的嫌

教你如何解決沒有資質讓金融貸款超市理財APP也能快速上架!

還記得剛進入金融行業時,專案老大跟我說現在APP上架審的蠻嚴格,不管是安卓市場還是蘋果市場,之前產品一直沒有上架成功,你看下有沒有什麼辦法。之前一直從事的都是非金融行業,比如智慧硬體、物聯網或者線上教育,這些產品有些會涉及到直播問題,會相對遇到一定的阻力,其他的大多數情況下都是很容易上架的,基本

使用 Android Studio 檢測記憶體洩漏解決記憶體洩漏問題

  本文在騰訊技術推文上 修改 釋出。     http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.195040.TASKID&ADUIN=913337456&a

使用C++11解決記憶體洩漏的問題

C++語言中沒有垃圾回收機制,必須自己去釋放分配的堆記憶體,否則就會記憶體洩漏。相信大部分C++開發人員都遇到過記憶體洩漏的問題,而查詢記憶體寫了的問題往往要花大量的精力。 解決這個問

webview api介紹+解決記憶體洩漏+js互動

1:建立webview 一般建立webview不採用在layout中直接去定義,而是用程式碼new一個webview出來,並且用RelativeLayout或LinearLayout做一個佔位. <LinearLayout android:id="@+id/wv_r

解決listview 中點選itemitem裡的所有設定了selector的元件全部一起變色

listview中如果不設定,item裡面的每個元件的背景顏色的話,預設情況下,點選item時,會有listview的預設,點選變色。預設的效果很醜,所以我們一般都會使用自定義的顏色。 現在我要實現這種效果,如上圖紅框中的兩個元件。這是一個listview,我想要實現

Instruments Leak解決記憶體洩漏問題

iOS 5.0之後apple引入了Xcode編譯器特性ARC(Automatic Reference Counting,自動引用計數)來幫助開發者管理記憶體,但為了追求app的高效能與減少安裝包大小,工作中很多時候需要我們手動管理記憶體。再牛的開發者也不能保證自己寫的co

Android:Handler 二三事(二)由記憶體洩漏所想到的(垃圾回收機制)

主要內容解決Handler記憶體洩漏以及延伸(垃圾回收、引用等)解決Handler記憶體洩漏及延伸為什麼Handler會引起記憶體洩漏?這是一段使用Handler的程式碼public class Lea