如何使用 PDFRender 更高效地渲染 pdf 并在 JetPack Compose 的 LazyColumn 中显示
How to do more efficient render a pdf with PDFRender and show in LazyColumn in JetPack Compose
我想从 FireStorage 下载一个 pdf 文件,呈现该文件,将每个页面(如 ImageBitMap)添加到列表中并显示在 LazyColumn 中。问题是尝试滚动非常慢,甚至在页面切换时冻结 4-5 秒。
关于如何使其更高效、更快速的任何想法?是否有 JetPack Compose 库可用于改进它?
谢谢
PDFScreen.kt
@Composable
fun PDFScreen(obraId: ObraId, autorId: AuthorId) {
val storageRef = FirebaseStorage.getInstance().reference
val pathReference = storageRef.child("obras/${autorId}/${obraId}.pdf")
val localFile = File.createTempFile("obra", "pdf")
var imageList = remember { mutableStateListOf<ImageBitmap?>(null) }
pathReference.getFile(localFile).addOnSuccessListener {
imageList.clear()
if (it.task.isSuccessful) {
val input = ParcelFileDescriptor.open(localFile, ParcelFileDescriptor.MODE_READ_ONLY)
val renderer = PdfRenderer(input)
for (i in 0 until renderer.pageCount) {
val page = renderer.openPage(i)
val bitmap =
Bitmap.createBitmap(Constants.width, Constants.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
imageList.add(bitmap.asImageBitmap())
page.close()
}
renderer.close()
}
}
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(items = imageList) { imagen ->
if (imagen != null) {
Image(
modifier = Modifier
.fillMaxSize(), bitmap = imagen, contentDescription = "Prueba"
)
}
}
}
}
您不应进行任何繁重的计算或直接从可组合函数中 db/network 调用。
所有复合函数都是视图构造函数,并且可以在可变状态的值发生变化时重新配置(例如,重新调用),对于动画 - 直到每一帧。在您的代码中,getFile
查询在将新项目添加到可变状态列表时执行,从而形成无限循环。
我建议你从解释基本原理的state in compose documentation, including this youtube video开始。
在您的情况下,应该将 fething 代码移至 view model:PDFScreenViewModel
对象将在视图出现时创建,并在视图离开视图层次结构时销毁:
class PDFScreenViewModel: ViewModel() {
val imageList = mutableStateListOf<ImageBitmap?>(null)
private val storageRef = FirebaseStorage.getInstance().reference
private val pathReference = storageRef.child("obras/${autorId}/${obraId}.pdf")
private val localFile = File.createTempFile("obra", "pdf")
init {
load()
}
fun load() {
pathReference.getFile(localFile).addOnSuccessListener {
imageList.clear()
if (it.task.isSuccessful) {
val input = ParcelFileDescriptor.open(localFile, ParcelFileDescriptor.MODE_READ_ONLY)
val renderer = PdfRenderer(input)
for (i in 0 until renderer.pageCount) {
val page = renderer.openPage(i)
val bitmap =
Bitmap.createBitmap(Constants.width, Constants.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
imageList.add(bitmap.asImageBitmap())
page.close()
}
renderer.close()
}
}
}
}
@Composable
fun PDFScreen(obraId: ObraId, autorId: AuthorId) {
val viewModel: PDFScreenViewModel = viewModel()
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(items = viewModel.imageList) { imagen ->
if (imagen != null) {
Image(
modifier = Modifier
.fillMaxSize(), bitmap = imagen, contentDescription = "Prueba"
)
}
}
}
}
我想从 FireStorage 下载一个 pdf 文件,呈现该文件,将每个页面(如 ImageBitMap)添加到列表中并显示在 LazyColumn 中。问题是尝试滚动非常慢,甚至在页面切换时冻结 4-5 秒。
关于如何使其更高效、更快速的任何想法?是否有 JetPack Compose 库可用于改进它?
谢谢
PDFScreen.kt
@Composable
fun PDFScreen(obraId: ObraId, autorId: AuthorId) {
val storageRef = FirebaseStorage.getInstance().reference
val pathReference = storageRef.child("obras/${autorId}/${obraId}.pdf")
val localFile = File.createTempFile("obra", "pdf")
var imageList = remember { mutableStateListOf<ImageBitmap?>(null) }
pathReference.getFile(localFile).addOnSuccessListener {
imageList.clear()
if (it.task.isSuccessful) {
val input = ParcelFileDescriptor.open(localFile, ParcelFileDescriptor.MODE_READ_ONLY)
val renderer = PdfRenderer(input)
for (i in 0 until renderer.pageCount) {
val page = renderer.openPage(i)
val bitmap =
Bitmap.createBitmap(Constants.width, Constants.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
imageList.add(bitmap.asImageBitmap())
page.close()
}
renderer.close()
}
}
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(items = imageList) { imagen ->
if (imagen != null) {
Image(
modifier = Modifier
.fillMaxSize(), bitmap = imagen, contentDescription = "Prueba"
)
}
}
}
}
您不应进行任何繁重的计算或直接从可组合函数中 db/network 调用。
所有复合函数都是视图构造函数,并且可以在可变状态的值发生变化时重新配置(例如,重新调用),对于动画 - 直到每一帧。在您的代码中,getFile
查询在将新项目添加到可变状态列表时执行,从而形成无限循环。
我建议你从解释基本原理的state in compose documentation, including this youtube video开始。
在您的情况下,应该将 fething 代码移至 view model:PDFScreenViewModel
对象将在视图出现时创建,并在视图离开视图层次结构时销毁:
class PDFScreenViewModel: ViewModel() {
val imageList = mutableStateListOf<ImageBitmap?>(null)
private val storageRef = FirebaseStorage.getInstance().reference
private val pathReference = storageRef.child("obras/${autorId}/${obraId}.pdf")
private val localFile = File.createTempFile("obra", "pdf")
init {
load()
}
fun load() {
pathReference.getFile(localFile).addOnSuccessListener {
imageList.clear()
if (it.task.isSuccessful) {
val input = ParcelFileDescriptor.open(localFile, ParcelFileDescriptor.MODE_READ_ONLY)
val renderer = PdfRenderer(input)
for (i in 0 until renderer.pageCount) {
val page = renderer.openPage(i)
val bitmap =
Bitmap.createBitmap(Constants.width, Constants.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
imageList.add(bitmap.asImageBitmap())
page.close()
}
renderer.close()
}
}
}
}
@Composable
fun PDFScreen(obraId: ObraId, autorId: AuthorId) {
val viewModel: PDFScreenViewModel = viewModel()
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(items = viewModel.imageList) { imagen ->
if (imagen != null) {
Image(
modifier = Modifier
.fillMaxSize(), bitmap = imagen, contentDescription = "Prueba"
)
}
}
}
}