中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

濟南做網站的公司電腦全自動掛機賺錢

濟南做網站的公司,電腦全自動掛機賺錢,北京市教學名師項目建設網站,網站產品頁面什么時候做案例3——view內存泄漏 前文提到,profile#Leaks視圖無法展示非Activity、非Fragment的內存泄漏,換言之,除了Activity、Fragment的內存泄漏外,其他類的內存問題我們只能自己檢索hprof文件查詢了。 下面有一個極佳的view內存泄漏例子…

案例3——view內存泄漏
前文提到,profile#Leaks視圖無法展示非Activity、非Fragment的內存泄漏,換言之,除了Activity、Fragment的內存泄漏外,其他類的內存問題我們只能自己檢索hprof文件查詢了。
下面有一個極佳的view內存泄漏例子,它的操作步驟為:

  1. 播放音樂,喚醒音樂懸浮窗
  2. 播放一段時間后,關閉音樂懸浮窗
  3. 重復步驟1和2

我們重復三次之后,得到一份hprof文件,下面我們來分析一下內存泄漏問題
在這里插入圖片描述

①輸入view的名稱
②選擇view
③可以看到分配了3個實例對象
④Instance List視圖顯示,view有3個實例對象及其引用
我們從上至下依次看3分實例的調用鏈

第一個泄漏點

view的第一個實例
先查看Fields區(qū)域,觀察mLayoutmode值,判斷view是否離開了窗口,如果已經離開了窗口,表明view未被回收,存在內存泄漏

在這里插入圖片描述
可以看到mLayoutMode = -1 ,表明布局已經離開屏幕了,此實例存在內存泄漏的情況
在這里插入圖片描述

接著我們查看References區(qū)域,逐級點開我們發(fā)現(xiàn)Handler發(fā)送的Message持有了當前view,導致view在離開窗口的時候,無法被垃圾回收器回收。
右鍵點擊查看問題代碼

在這里插入圖片描述
問題代碼:

   playHandler.post(new Runnable() {@Overridepublic void run() {tv_play.setText(playItem.getProgramTitle());tb_play.setSelected(true);initView();}});

看到new Runnbale,這是是匿名內部類,匿名內部類持有當前類的引用,匿名Runnbale未執(zhí)行完畢,Runnbale內存未釋放的時候,view就無法被釋放,而匿名Runnbale的釋放時機不可控,由Handler、Looper、Runnbale執(zhí)行情況影響。
那么我們該怎么優(yōu)化呢?

  1. 使用非匿名或靜態(tài)的Handler+弱引用,處理此任務
  2. 在主線程處理此任務
  3. view退出的時候釋放Message對view的引用
    筆者采用了方案3:
tv_play.setText(playItem.getProgramTitle());
tb_play.setSelected(true);
initView();

方案1代碼與下面view的第三個實例寫法一致,不重復寫了;我們解釋一下方案3:

view退出的時候釋放Message對view的引用
根據(jù)上圖所示,我們看到Message-Runnbale-View的引用關系可知,Looper中的Message持續(xù)的引用view,我們最高效釋放內存的做法是view離開窗口的時候,斬斷Message與view的引用關系,那么我們該怎么做呢?答案是:

  1. 結束子線程任務
  2. 清空Looper緩存的Message
  3. 釋放Handler

第一步:結束子線程任務很簡單
thread.interrupt()
本案例給Handler傳入的是Runnbale,Handler未提供結束Runnbale的接口,此項優(yōu)化擱置
第二步:清空Message
已知Looper提供了清空Message的接口

  1. Looper#quit
  2. Looper#quitSafely
  3. 主線程的Looper無法退出
    已知Handler提供了釋放Message的接口
  4. Handler#removeCallbacksAndMessages
    那我們優(yōu)化起來就很簡單了,清空Handler持有的Message
@Override protected void onDetachedFromWindow() { 
super.onDetachedFromWindow(); ... // 釋放message,斷開message-Runnbale-view的引用鏈 if (playHandler != null) { playHandler.removeCallbacksAndMessages(null); playHandler = null; }}

第二個泄漏點

我們繼續(xù)看view的第二個實例
先查看Fields區(qū)域,觀察mLayoutmode值,判斷view是否離開了窗口,如果已經離開了窗口,表明view未被回收,存在內存泄漏

在這里插入圖片描述
可以看到mLayoutMode = -1 ,表明布局已經離開屏幕了,此實例存在內存泄漏的情況
接著我們看References區(qū)域,觀察調用鏈
在這里插入圖片描述
可以看到MediaPlayerIml有一個成員變量mMediaPlayListenerCacheList,緩存了MediaPlayListener,MediaPlayListener又是在view實例里面創(chuàng)建的,并且作為內部類,它持有view的實例。現(xiàn)在我們得到了清晰的調用鏈,MediaPlayerIml->mMediaPlayListenerCacheList->MediaPlayListener->view,MediaPlayerIml引用view導致view實例無法被釋放
查看問題代碼:
筆者發(fā)現(xiàn)view#onDetachedFromWindow已經觸發(fā)了移除list#listener操作

@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mediaPlayerIml.unregisterListener(playListener); 

可以看到內部實現(xiàn)是remove調引用的

 /*** 取消注冊listener** @param listener*/public synchronized void unregisterListener(MediaPlayListener listener) {mMediaPlayListenerCacheList.remove(listener);}

那為什么會未回收持續(xù)占用內存呢?

  1. 抓拍hprof文件期間,代碼未執(zhí)行到unregisterListener,導致view內存未得到釋放
  2. mMediaPlayListenerCacheList添加的listener與remove的listener不是同一個
  3. 此處沒有產生內存泄漏,判斷view是否應該被回收的依據(jù)有問題

第三個泄漏點

擱置疑問,接著我們來看view的第三個實例,節(jié)省時間,筆者直接調到代碼索引出,展示問題代碼:

  /*** 播放進度條刷新控*/private Handler m_handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case MSG_FLUSH_SEEKBAR:boolean isPlaying = mediaPlayerIml != null && mediaPlayerIml.getPlayStatus() == QingtingConfig.PLAY;if (isPlaying) {int currentTime = mediaPlayerIml.getCurrentTime();int totalTime = mediaPlayerIml.getTotalTime();mSeekBar.setMax(totalTime);mSeekBar.setProgress(currentTime);mPrograssBar.setMaxProgress(totalTime);mPrograssBar.setCurrentProgress(currentTime);LoggerUtils.instance().logE("mediaPlayJindu", "mediaPlayJindu" + totalTime + "/" + currentTime);}m_handler.sendEmptyMessageDelayed(MSG_FLUSH_SEEKBAR, MSG_FLUSH_TIME);break;}}};

可以看到此處還是使用了非靜態(tài)內部類m_handler,m_handler持有當前view 的引用,m_handler如果長期存在,那么view的內存也不會被釋放
解決方法如下:

  1. 定義外部類Handler
  2. 定義靜態(tài)內部類
  3. 定義靜態(tài)內部類+弱引用
    筆者采用了方案3:
    定義靜態(tài)內部類
 private  static  class UpdateHandler extends Handler {private final WeakReference<MediaPlayerIml> mediaPlayerImlWeakReference;private final WeakReference<SeekBar> seekBarWeakReference;private final WeakReference<QQCircleProgressBar> progressBarWeakReference;public UpdateHandler(MediaPlayerIml mediaPlayerIml, SeekBar seekBar, QQCircleProgressBar progressBar) {mediaPlayerImlWeakReference = new WeakReference<MediaPlayerIml>(mediaPlayerIml);seekBarWeakReference = new WeakReference<SeekBar>(seekBar);progressBarWeakReference = new WeakReference<QQCircleProgressBar>(progressBar);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == MSG_FLUSH_SEEKBAR) {MediaPlayerIml mediaPlayerIml = mediaPlayerImlWeakReference.get();SeekBar seekBar = seekBarWeakReference.get();QQCircleProgressBar qqCircleProgressBar =progressBarWeakReference.get();boolean isPlaying = mediaPlayerIml != null && mediaPlayerIml.getPlayStatus() == QingtingConfig.PLAY;if (isPlaying && seekBar!=null && qqCircleProgressBar != null) {int currentTime = mediaPlayerIml.getCurrentTime();int totalTime = mediaPlayerIml.getTotalTime();seekBar.setMax(totalTime);seekBar.setProgress(currentTime);qqCircleProgressBar.setMaxProgress(totalTime);qqCircleProgressBar.setCurrentProgress(currentTime);LoggerUtils.instance().logE("mediaPlayJindu", "mediaPlayJindu" + totalTime + "/" + currentTime);}sendEmptyMessageDelayed(MSG_FLUSH_SEEKBAR, MSG_FLUSH_TIME);}}}

在view使用時,初始化handler,構造參數(shù)傳入組件id;

m_handler = new UpdateHandler(MediaPlayerIml.getInstance(),mSeekBar,mPrograssBar);
m_handler.sendEmptyMessage(MSG_FLUSH_SEEKBAR);

在view離開窗口時候,銷毀handler數(shù)據(jù);

  @Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();...if(m_handler!=null){m_handler.removeCallbacksAndMessages(null);m_handler = null;}}

總結

總結我們針對此按理做的優(yōu)化

  1. 靜態(tài)Handler+弱引用,釋放了對handler對view的引用,讓view及時銷毀,view占據(jù)的內存及時被垃圾回收器釋放
  2. 釋放了Message對view的引用,在view及時退出界面的時候,立即斬斷message對view
    回顧一下優(yōu)化前的實例數(shù)量,多次操作,隱藏展示懸浮窗之后,內存中存在多份懸浮窗實例,之前創(chuàng)建過的懸浮窗內存一直無法被回收:
    在這里插入圖片描述
    優(yōu)化后效果,多次操作,當屏幕上存在一個view時,只存在一份view實例:
    [圖片]
http://www.risenshineclean.com/news/35776.html

相關文章:

  • 公務員建設文化與道德網站營銷網站優(yōu)化推廣
  • 廣西網站建設蘇州網站制作
  • 做傳銷網站違法嗎品牌推廣策略分析
  • 做自己的網站可以賺錢嗎市場推廣方案怎么寫
  • 織夢做的網站 xampp百度seo排名主要看啥
  • 做外貿開通哪個網站好seo優(yōu)化排名易下拉用法
  • 淘寶客做軟件網站app廣州百度競價托管
  • 做網站需要自備服務器嗎市場營銷培訓
  • 北京網站建設 優(yōu)化seo優(yōu)化專員
  • 做中醫(yī)藥網站有前景嗎山東企業(yè)網站建設
  • 網絡信息安全網站開發(fā)教程網站權重查詢接口
  • 網站建設win2012百度如何發(fā)布信息推廣
  • 用訂制音樂網站做的音樂算原創(chuàng)嗎人工智能培訓班收費標準
  • 網站建設規(guī)模與類別蘇州百度推廣排名優(yōu)化
  • b2b網站的功能上??焖賰?yōu)化排名
  • 做分類網站用什么cms谷歌網頁版登錄入口
  • 云南網站優(yōu)化建站seo優(yōu)化點擊軟件
  • 四川航霖管理咨詢有限公司seo站長常用工具
  • 招聘網站的SEO怎么做網站推廣軟件費用是多少
  • 做網站靠教育賺錢網絡營銷和傳統(tǒng)營銷的關系
  • 泰州營銷型網站2345瀏覽器主頁網址
  • 男女做床上網站微信朋友圈廣告投放代理
  • 網站建設 駿域網絡建設專家廣州推廣策劃方案怎么做
  • 80s網站建設工作室鄭州網站建設七彩科技
  • 做公司網站推廣百度指數(shù)是啥
  • 圣融網站建設如何推廣一個平臺
  • 江西省網站備案平面設計培訓費用一般是多少
  • 網站建設經營范圍seo項目培訓
  • 張家港企業(yè)做網站seo網站運營
  • 保定網站建設方法能打開各種網站的瀏覽器下載