国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

濟(jì)南做網(wǎng)站的公司電腦全自動(dòng)掛機(jī)賺錢

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

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

  1. 播放音樂(lè),喚醒音樂(lè)懸浮窗
  2. 播放一段時(shí)間后,關(guān)閉音樂(lè)懸浮窗
  3. 重復(fù)步驟1和2

我們重復(fù)三次之后,得到一份hprof文件,下面我們來(lái)分析一下內(nèi)存泄漏問(wèn)題
在這里插入圖片描述

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

第一個(gè)泄漏點(diǎn)

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

在這里插入圖片描述
可以看到mLayoutMode = -1 ,表明布局已經(jīng)離開(kāi)屏幕了,此實(shí)例存在內(nèi)存泄漏的情況
在這里插入圖片描述

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

在這里插入圖片描述
問(wèn)題代碼:

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

看到new Runnbale,這是是匿名內(nèi)部類,匿名內(nèi)部類持有當(dāng)前類的引用,匿名Runnbale未執(zhí)行完畢,Runnbale內(nèi)存未釋放的時(shí)候,view就無(wú)法被釋放,而匿名Runnbale的釋放時(shí)機(jī)不可控,由Handler、Looper、Runnbale執(zhí)行情況影響。
那么我們?cè)撛趺磧?yōu)化呢?

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

方案1代碼與下面view的第三個(gè)實(shí)例寫法一致,不重復(fù)寫了;我們解釋一下方案3:

view退出的時(shí)候釋放Message對(duì)view的引用
根據(jù)上圖所示,我們看到Message-Runnbale-View的引用關(guān)系可知,Looper中的Message持續(xù)的引用view,我們最高效釋放內(nèi)存的做法是view離開(kāi)窗口的時(shí)候,斬?cái)郙essage與view的引用關(guān)系,那么我們?cè)撛趺醋瞿?#xff1f;答案是:

  1. 結(jié)束子線程任務(wù)
  2. 清空Looper緩存的Message
  3. 釋放Handler

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

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

第二個(gè)泄漏點(diǎn)

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

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

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

可以看到內(nèi)部實(shí)現(xiàn)是remove調(diào)引用的

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

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

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

第三個(gè)泄漏點(diǎn)

擱置疑問(wèn),接著我們來(lái)看view的第三個(gè)實(shí)例,節(jié)省時(shí)間,筆者直接調(diào)到代碼索引出,展示問(wèn)題代碼:

  /*** 播放進(jìn)度條刷新控*/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)內(nèi)部類m_handler,m_handler持有當(dāng)前view 的引用,m_handler如果長(zhǎng)期存在,那么view的內(nèi)存也不會(huì)被釋放
解決方法如下:

  1. 定義外部類Handler
  2. 定義靜態(tài)內(nèi)部類
  3. 定義靜態(tài)內(nèi)部類+弱引用
    筆者采用了方案3:
    定義靜態(tài)內(nè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使用時(shí),初始化handler,構(gòu)造參數(shù)傳入組件id;

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

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

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

總結(jié)

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

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

相關(guān)文章:

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