我想優化我的 recyclerview,我正在開發一個 pdf 閱讀器,我發現了一個小函式來顯示我的 pdf 檔案的第一頁:
private fun pdfToBitmap(pdfFile: File): Bitmap? {
var bitmap: Bitmap? = null
try {
val renderer = PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY))
val pageCount = renderer.pageCount
if (pageCount > 0) {
val page = renderer.openPage(0)
bitmap = Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
canvas.drawBitmap(bitmap, page.width.toFloat(), page.height.toFloat(), null)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
page.close()
renderer.close()
}
} catch (ex: Exception) {
ex.printStackTrace()
}
return bitmap
}
我在默認的協程調度程式中執行它,并在主執行緒中顯示它,它給了我這種非常奇怪的行為。預覽在它們之間隨機交換,我也想快取這些位圖,也許它可以幫助解決這個問題。
這是我的錯誤:
動圖
謝謝
uj5u.com熱心網友回復:
RecyclerViews 通過創建一些專案布局并重用它們來顯示其他專案(回收它們,因此得名)來作業。當 aViewHolder需要顯示一個新專案時,onBindViewHolder就會被呼叫,這就是您在專案布局中設定視圖的地方 - 設定文本、更改影像等。
因此,如果 ViewHolder #4 顯示某個影像,然后您向下滾動到 ViewHolder #4 被重用的位置,它仍會顯示該影像,直到您更改它。猜測一下,您的影像渲染代碼非常慢,因此實際發生更改需要很長時間。你也可能會遇到這樣的情況,如果你滾動得足夠遠,#4 會再次使用,現在你有兩個渲染任務排隊,所以你可能會看到影像改變了兩次,等等。
您最簡單的解決方案可能是始終顯示占位符 PDF 影像,然后啟動渲染器任務 - 這樣當您滾動到新專案時,它永遠不會暫時顯示錯誤的影像。但是您仍然需要取消陳舊的協程作業 - 將display函式放在ViewHolder自身中可能是值得的,因此它可以觸發任務,保留自己的Job參考,并在有新display呼叫時取消它。
您可以使用快取,如LRU 快取或磁盤快取 - 它肯定有助于提高性能,但它會使事情變得有點復雜,并且有很多不同的解決方案。如果你想走這條路,你必須做一些調查,看看你正在做的事情的正確方法是什么。
這是 Android 檔案中關于有效位圖加載的頁面 - 我主要鏈接這個,因為它們鏈接到一些您可以查看的推薦庫。其中一些處理從檔案加載,因此如果您正在執行臨時磁盤快取路由,它可能會很有用。您將不得不看到將它們與您正在使用的渲染器集成是多么容易(因為您所做的比“加載影像”要復雜一些)
不過有一個建議 - 看起來您正在創建完整 PDF 頁面大小的位圖。我不確定您是否需要在渲染階段執行此操作,但您肯定會根據串列中影像視圖的實際大小調整顯示的大小。這些庫處理智能調整大小以適應視圖 - 但即使您不使用它們,您自己的快取也將受益于處理更小的位圖
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/442551.html
