亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

出現的現象就是滑動不流暢,操作出現反應遲延,該怎么解決?

出現的現象就是滑動不流暢,操作出現反應遲延,該怎么解決?

三國紛爭 2023-04-16 10:06:54
我在一個Activity中有一個大的ListView(ListView中的每個Item填充的東西比較多,還有大量圖片),出現的現象就是滑動不流暢,操作出現反應遲延,在LogCat中頻繁的打印GC_EXPLICIT,通過網上了解,應該是內錯的問題,之所以反應遲鈍,滑動不流暢是因為要等待內存釋放,重新申請新的內存,但是不知道怎么解決。請有經驗的高手指點。完整的幾條logcat:11-17 10:19:45.257: D/dalvikvm(22511): GC_EXPLICIT freed 14K, 52% free 3715K/7687K, external 7372K/9177K, paused 25ms11-17 10:19:45.414: D/dalvikvm(22511): GC_EXPLICIT freed 14K, 52% free 3715K/7687K, external 7372K/9177K, paused 26ms11-17 10:19:45.722: D/dalvikvm(22511): GC_EXPLICIT freed 39K, 52% free 3717K/7687K, external 7372K/9177K, paused 25ms11-17 10:19:45.875: D/dalvikvm(22511): GC_EXPLICIT freed 13K, 52% free 3717K/7687K, external 7372K/9177K, paused 25ms
查看完整描述

1 回答

?
偶然的你

TA貢獻1841條經驗 獲得超3個贊

已經大半年不碰Android了,以下是一些記憶中的經驗,供參考。

首先確實是內存問題,這些都是DalvikVM的GC日志,格式如下:

[GC原因] [釋放了多少VM內存], [VM堆內存統計], [外部內存統計], [VM暫停時間]

其中[原因]的內容可以參考Android源碼中/dalvik/vm/alloc/Heap.h中enum GcReason的定義:

typedef enum {
    /* Not enough space for an "ordinary" Object to be allocated. */    GC_FOR_MALLOC,
    /* Automatic GC triggered by exceeding a heap occupancy threshold. */    GC_CONCURRENT,
    /* Explicit GC via Runtime.gc(), VMRuntime.gc(), or SIGUSR1. */    GC_EXPLICIT,
    /* GC to try to reduce heap footprint to allow more non-GC'ed memory. */    GC_EXTERNAL_ALLOC,
    /* GC to dump heap contents to a file, only used under WITH_HPROF */    GC_HPROF_DUMP_HEAP} GcReason;

你日志中的GC_EXPLICIT就是說有調用過Runtime.gc()或VMRuntime.gc()(可能是SDK調的)。然后[VM暫停時間]是“hold the whole world”,就是所有東西都停止,會非常影響體驗,就是造成你覺得操作卡頓的主要原因。

然后是解決方案。在ListView/GridView之類的東西里面展現圖片很容易就會遇上內存問題,說白了就是內存里的圖片太大內存不足,好點的引發GC卡頓,差點的就直接OOM了。所以有幾個解決思路:

1. 減少圖片文件大小
調整圖片大小或是降低圖片色彩值或是修改圖片格式都可以有效降低圖片文件大小。例如色彩較豐富的圖片jpg就比png要小一些,能做點九的盡量點九,減少色彩值數量可以顯著降低png圖片大小,特別是如果可以控制在256種顏色之內就可以啟動png的色彩索引方案,加大jpg的壓縮比例也可以讓圖片小很多。此方案的缺點則是圖片必須是由我們自己處理的,例如靜態資源或是從自己服務器獲取的圖,可以做預先處理。

2. 減少圖片在內存中的大小
圖片文件有多大并不代表它在內存里就占用多少空間,因為我們可以在圖片加載過程中對其數據進行一些修改以達到減少在內存中占用的效果。一般來說有兩種辦法:
1) 動態修改圖片色值,例如從8888改為565這種,以前我們用過對大圖片非常有效。
2) 先用僅讀取圖片的bounds,然后依此縮小圖片(代碼網上很多),銷毀掉大圖僅使用小圖,再做顯示處理,也是一個常用方法。

3. 更好的利用內存
首先要理解Android中bitmap用的是native的內存,你可以理解為是C用的那段內存,與java用的不在一起。Android從3.2版本以后加強了這塊的管理,使得native內存會隨著JVM的GC一起回收,所以會大大減少這塊的問題(3.2之前的版本也會回收,但因為與Java GC不同步所以一般回收不及時就會暴內存溢出,因此需要開發者手工調用recycle())

然后遵循一條法則:“永遠只存放要顯示的圖片在內存中”,也就是說只有用戶看得見的圖片才在內存里,看不見的就銷毀(recycle()),需要時再重新加載。這點與ListView的滑動窗口是一個道理。

要做到這些,recycle()總是需要自己寫邏輯(對于3.2之前的版本),但留在JVM內存的那部分可以交給系統來管理,以前較為常用的建議是SoftReference和WeakReference,現在一般建議使用Android自帶的緩存類LruCache或LruDiskCache,它會自動按照LRU算法銷毀隊列尾部的元素(最不常用),而非看GC心情。

另外樓主也應該盡量減少View的個數,能合并的盡量合并,盡量少使用重量級的View(可以查看View的源碼由其成員變量組成來確定是輕是重)。如果以上這些都做了依然有大量的GC,建議在業務可接受的范圍內與產品討論簡化界面。


查看完整回答
反對 回復 2023-04-19
  • 1 回答
  • 0 關注
  • 209 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號