使用Handler出現的警告
零、原由
安卓中使用Hander時出現了如下警告:
This Handler class should be static or leaks might occur (anonymous android.os.Handler)
網上建議使用如下方案:
private Handler mHandler2 = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
但是又出現了如下警告:
'Handler(android.os.Handler.Callback)' is deprecated
都與內存泄漏有關,在API級別30中,Handler(Handler.Callback)構造函數被棄用。Android在這里解釋了原因。
public Handler (Handler.Callback callback)
此構造函數已棄用。在處理程序構造期間隱式地選擇一個循環器可能會導致錯誤,其中操作會自動丟失(如果處理程序不希望有新任務並退出)、崩潰(如果處理程序有時在thread上創建而沒有活動循環器)或爭用條件,threada處理程序所關聯的地方並不是作者所預期的。相反,請使用執行器或顯式指定循環器,使用Looper\getMainLooper、{linkandroid.view.View#getHandler}或類似的方法。如果為了兼容性需要隱式thread本地行為,請使用newHandler(Looper.myLooper(),callback)向讀者說明。
壹、解決方案
使用Handler(Looper,Handler.Callback)構造函數並顯式指定循環器。
案例1:如果您希望代碼在main/UI thread上運行
Handler handler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
// Your code logic here
return true;
}
});
案例2:如果你想讓代碼在后台運行thread
// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
// Using this handler to post tasks that running on a background thread.
Handler handler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
// Your code logic here
return true;
}
});
記住完成后釋放thread。
handlerThread.quit(); // 或者是 handlerThread.quitSafely();
案例3:如果希望代碼在后台thread上運行,並將結果返回main/UI thread。
// Using this handler to post tasks that run on main/UI thread
Handler uiHandler = new Handler(Looper.getMainLooper());
// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
// Using this handler to post task that run on a background thread
Handler handler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
// Your code logic here
// Execute the code or pass the result back to main/UI thread
uiHandler.post(new Runnable() {
@Override
public void run() {
}
});
return true;
}
});
貳、效果
public class MainActivity extends AppCompatActivity {
private final Handler handler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
已經沒有警告了。