使用軟引用解決Handler記憶體洩露和顯示Popupwindow、Dialog時提示"Unable to add Window-token is null"的問題
原文連結:http://zmywly8866.github.io/2015/09/22/softreferences-in-android.html
通過軟引用解決Handler記憶體洩露的問題
下面對軟引用使用的方式適用於任何內部類,嚴格來說是通過軟引用解決靜態內部類無法呼叫當前類中的物件和方法的問題,真正解決記憶體洩露是需要將內部類改成靜態內部類。
當在一個類中按照如下方式建立一個Handler內部類時,使用Lint工具檢測時會給出“This Handler class should be static or leaks might occur”的警告,原因是Handler內部類可能持有當前類的引用,導致即使該類不再被使用時系統仍無法回收這給類持有的物件,Android中記憶體洩露很多都是由於持有類中的物件時間太長導致,如果很多地方出現類似的程式碼會導致應用佔用的記憶體不斷上漲,最終導致程式崩潰。
private TextView mUserNameTxt = null;
class LoadDataHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case 0:{
mUserNameTxt.setText(msg.obj.toString());
}
break;
default:{
}
break;
}
}
}
按照Lint的建議將Handler內部類改成static靜態內部類後,由於不可能將當前類的所有全域性物件都宣告為static物件,所以會報“Cannot make a static reference to the non-static field”的錯誤,這時候可以使用軟引用來解決這個問題,具體程式碼如下:
private TextView mUserNameTxt = null;
static class LoadDataHandler extends Handler{
private SoftReference<MainActivity> activitySRF = null;
public LoadDataHandler(MainActivity activity){
activitySRF = new SoftReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 因為Handler是非同步的,存在退出當前類之後才接收到handler訊息的情況,並且軟引用持有的物件會在堆記憶體不足時存在被回收的可能,所以這裡需要判空處理
if(null == activitySRF || null == activitySRF.get()){
return;
}
switch(msg.what){
case 0:{
activitySRF.get().mUserNameTxt.setText(msg.obj.toString());
}
break;
default:{
}
break;
}
}
}
通過軟引用解決銷燬某個Activity後,仍然在Activity顯示Popupwindow或者Dialog時提示”Unable to add Window-token is null”的問題
在實際專案中踩過這個坑,特地分享出來,這個問題是由於在Activity中顯示PopupWindow或者Dialog時,PopupWindow、Dialog還沒顯示出來就銷燬了當前Activity導致(主要是快速切換)。因為PopupWindow和Dialog都是依附於當前Activity的某個View上的,當前Activity被銷燬後依附的view為空,此時顯示PopupWindow或者Dialog時會提示這個異常。
這個問題也可以通過軟引用來解決(通過判斷軟引用中的activity物件是否為空或者是否已經finish即可判斷是否可以顯示PopupWindow或者Dialog),具體程式碼如下:
private SoftReference<Activity> activitySRF = null;
public void initDialog(Activity activity){
activitySRF = new SoftReference<Activity>(activity);
if(null != activitySRF&&null!=activitySRF.get()&&!activitySRF.get().isFinishing()){
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
show();
setContentView(R.layout.hanzi_medal_dialoglayout);
setCanceledOnTouchOutside(true);
setCancelable(false);
}
}
public void show(Activity activity, String medalName){
initDialog(activity);
if(null != activitySRF&&null!=activitySRF.get()&&!activitySRF.get().isFinishing()){
TextView medalTxt = (TextView) findViewById(R.id.medalTxtId);
if (!TextUtils.isEmpty(medalName)) {
medalTxt.setText("恭喜您獲得“" + medalName + "”勳章");
}
new Handler(activitySRF.get().getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
if(null != activitySRF&&null!=activitySRF.get()&&!activitySRF.get().isFinishing()){
dismiss();
}
}
}, 3000);
}
}
相關文章
- 解決git記憶體洩露問題Git記憶體洩露
- 難解決的記憶體洩露(OutOfMemory)問題!!!記憶體洩露
- Android在Dialog中顯示PopupWindow不全問題解決Android
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- Android中使用Handler造成記憶體洩露的分析和解決Android記憶體洩露
- react 記憶體洩露常見問題解決方案React記憶體洩露
- 記憶體洩露引起的問題記憶體洩露
- ThreaLocal記憶體洩露的問題記憶體洩露
- Handler的使用、記憶體洩漏和解決記憶體
- android Handler導致的記憶體洩露Android記憶體洩露
- Android中Handler引起的記憶體洩露Android記憶體洩露
- Android 中 Handler 引起的記憶體洩露Android記憶體洩露
- 內部Handler類引起記憶體洩露記憶體洩露
- JVM與記憶體洩露問題JVM記憶體洩露
- Handler記憶體洩漏分析及解決記憶體
- Scrapy的記憶體洩露問題總結記憶體洩露
- 談談.NET中常見的記憶體洩露問題——GC、委託事件和弱引用記憶體洩露GC事件
- Js記憶體洩露問題總結JS記憶體洩露
- JAVA記憶體洩露的原因及解決Java記憶體洩露
- Handler記憶體洩漏原因及解決方案記憶體
- 使用Windbg快速分析應用記憶體洩露問題記憶體洩露
- PHP的記憶體洩露問題與垃圾回收PHP記憶體洩露
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- 記憶體洩露記憶體洩露
- 【c++】vector.clear()的記憶體洩露問題C++記憶體洩露
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- Java 記憶體洩露的理解與解決過程Java記憶體洩露
- JAVA 記憶體洩露詳解(原因、例子及解決)Java記憶體洩露
- 如何定位和解決記憶體洩露記憶體洩露
- .Net記憶體洩露原因及解決辦法記憶體洩露
- 避免使用Handler而造成的記憶體洩漏記憶體
- SQL Server 記憶體洩露(memory leak)——遊標導致的記憶體問題SQLServer記憶體洩露
- Android 記憶體洩露詳解Android記憶體洩露
- js記憶體洩露JS記憶體洩露
- JavaScript記憶體洩露JavaScript記憶體洩露
- 記憶體洩露嗎記憶體洩露
- SHBrowseForFolder 記憶體洩露記憶體洩露
- 分析ThreadLocal的弱引用與記憶體洩漏問題thread記憶體