Skip to content

Some proposed changes for your consideration #186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ dependencies {

implementation("com.google.android.material:material:1.12.0")
implementation("androidx.test.espresso:espresso-contrib:3.6.1")
val kotlin_version = "1.9.21"
val kotlin_version = "2.1.10"
implementation(kotlin("stdlib"))
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
//noinspection GradleDependency
Expand Down
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

plugins {
id("com.android.application") version "8.8.1" apply false
id("org.jetbrains.kotlin.android") version "1.9.20" apply false
id("com.android.library") version "8.8.1" apply false
id("com.android.application") version "8.9.0" apply false
id("org.jetbrains.kotlin.android") version "2.1.10" apply false
id("com.android.library") version "8.9.0" apply false
}
5 changes: 3 additions & 2 deletions pdfViewer/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.vanniktech.maven.publish.SonatypeHost
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
id("kotlin-parcelize")
id("org.jetbrains.dokka") version "1.9.20"
id("com.vanniktech.maven.publish") version "0.28.0"
Expand Down Expand Up @@ -52,7 +53,7 @@ android {

dependencies {
implementation("androidx.compose.material3:material3-android:1.3.1")
val kotlin_version = "1.9.21"
val kotlin_version = "2.1.10"
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version")
implementation("androidx.core:core-ktx:1.15.0")
Expand Down Expand Up @@ -121,4 +122,4 @@ mavenPublishing {
}
}

}
}
30 changes: 9 additions & 21 deletions pdfViewer/src/main/java/com/rajat/pdfviewer/PdfRendererCore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import java.nio.file.Files
import java.nio.file.Paths
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.abs

open class PdfRendererCore(
private val context: Context,
Expand Down Expand Up @@ -84,19 +83,19 @@ open class PdfRendererCore(

fun renderPage(
pageNo: Int,
bitmap: Bitmap,
onBitmapReady: ((success: Boolean, pageNo: Int, bitmap: Bitmap?) -> Unit)? = null
size: Size,
onBitmapReady: ((pageNo: Int, bitmap: Bitmap?) -> Unit)? = null
) {
val startTime = System.nanoTime()

if (pageNo >= getPageCount()) {
onBitmapReady?.invoke(false, pageNo, null)
onBitmapReady?.invoke(pageNo, null)
return
}

getBitmapFromCache(pageNo)?.let { cachedBitmap ->
scope.launch(Dispatchers.Main) {
onBitmapReady?.invoke(true, pageNo, cachedBitmap)
onBitmapReady?.invoke(pageNo, cachedBitmap)
if (enableDebugMetrics) {
Log.d("PdfRendererCore", "Page $pageNo loaded from cache")
}
Expand All @@ -108,7 +107,6 @@ open class PdfRendererCore(

renderJobs[pageNo]?.cancel()
renderJobs[pageNo] = scope.launch {
var success = false
var renderedBitmap: Bitmap? = null

renderLock.withLock {
Expand All @@ -117,14 +115,13 @@ open class PdfRendererCore(

try {
val aspectRatio = pdfPage.width.toFloat() / pdfPage.height
val height = bitmap.height
val height = size.height
val width = (height * aspectRatio).toInt()

val tempBitmap = CommonUtils.Companion.BitmapPool.getBitmap(width, height)
pdfPage.render(tempBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)

addBitmapToMemoryCache(pageNo, tempBitmap)
success = true
renderedBitmap = tempBitmap

} catch (e: Exception) {
Expand All @@ -144,26 +141,19 @@ open class PdfRendererCore(
updateAggregateMetrics(pageNo, renderTime)

withContext(Dispatchers.Main) {
onBitmapReady?.invoke(success, pageNo, renderedBitmap)
onBitmapReady?.invoke(pageNo, renderedBitmap)
}
}
}

suspend fun renderPageAsync(pageNo: Int, width: Int, height: Int): Bitmap? {
return suspendCancellableCoroutine { continuation ->
val bitmap = CommonUtils.Companion.BitmapPool.getBitmap(width, height)
renderPage(pageNo, bitmap) { success, _, renderedBitmap ->
if (success) {
continuation.resume(renderedBitmap ?: bitmap, null)
} else {
CommonUtils.Companion.BitmapPool.recycleBitmap(bitmap)
continuation.resume(null, null)
}
renderPage(pageNo, Size(width, maxOf(1, height))) { _, renderedBitmap ->
continuation.resume(renderedBitmap, null)
}
}
}


private fun updateAggregateMetrics(page: Int, duration: Long) {
totalPagesRendered++
totalRenderTime += duration
Expand All @@ -186,9 +176,7 @@ open class PdfRendererCore(
if (renderJobs[pageNo]?.isActive != true) {
renderJobs[pageNo]?.cancel()
renderJobs[pageNo] = scope.launch {
val bitmap = CommonUtils.Companion.BitmapPool.getBitmap(width, height)
renderPage(pageNo, bitmap) { success, _, _ ->
if (!success) CommonUtils.Companion.BitmapPool.recycleBitmap(bitmap)
renderPage(pageNo, Size(width, maxOf(1, height))) { _, _ ->
}
}
}
Expand Down
52 changes: 44 additions & 8 deletions pdfViewer/src/main/java/com/rajat/pdfviewer/PdfViewAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package com.rajat.pdfviewer

import android.content.Context
import android.graphics.Rect
//import android.util.Log
import android.util.Size
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AlphaAnimation
import android.view.animation.LinearInterpolator
import androidx.recyclerview.widget.RecyclerView
import com.rajat.pdfviewer.databinding.ListItemPdfPageBinding
import com.rajat.pdfviewer.util.CommonUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -34,9 +35,47 @@ internal class PdfViewAdapter(
holder.bind(position)
}

override fun onViewRecycled(holder: PdfPageViewHolder) {
holder.recycle()
}

override fun onViewDetachedFromWindow(holder: PdfPageViewHolder) {
holder.detach()
}

override fun onViewAttachedToWindow(holder: PdfPageViewHolder) {
holder.attach(holder.bindingAdapterPosition)
}

inner class PdfPageViewHolder(private val itemBinding: ListItemPdfPageBinding) : RecyclerView.ViewHolder(itemBinding.root) {
private var detached = false

private fun clearBitmap() {
with(itemBinding) {
pageView.setImageBitmap(null);
}
detached = true
}

fun attach(position: Int) {
// Log.d("PdfViewAdapter", "Attached to window: $bindingAdapterPosition")
if ( detached )
bind(position)
}

fun detach() {
// Log.d("PdfViewAdapter", "Detached from window: $bindingAdapterPosition")
clearBitmap()
}

fun recycle() {
// Log.d("PdfViewAdapter", "Recycled page: $bindingAdapterPosition")
clearBitmap()
}

fun bind(position: Int) {
with(itemBinding) {
// Log.d("PdfViewAdapter", "Binding page: $position")
pageLoadingLayout.pdfViewPageLoadingProgress.visibility = if (enableLoadingForPages) View.VISIBLE else View.GONE

// Before we trigger rendering, explicitly ensure that cached bitmaps are used
Expand All @@ -54,24 +93,21 @@ internal class PdfViewAdapter(

updateLayoutParams(height)

val bitmap = CommonUtils.Companion.BitmapPool.getBitmap(width, maxOf(1, height))
renderer.renderPage(position, bitmap) { success, pageNo, renderedBitmap ->
if (success && pageNo == position) {
renderer.renderPage(position, Size(width, maxOf(1, height))) { pageNo, renderedBitmap ->
if (renderedBitmap != null && pageNo == position) {
CoroutineScope(Dispatchers.Main).launch {
pageView.setImageBitmap(renderedBitmap ?: bitmap)
pageView.setImageBitmap(renderedBitmap)
applyFadeInAnimation(pageView)
pageLoadingLayout.pdfViewPageLoadingProgress.visibility = View.GONE
[email protected] = false

// Prefetch here
renderer.prefetchPagesAround(
currentPage = position,
width = pageView.width.takeIf { it > 0 } ?: context.resources.displayMetrics.widthPixels,
height = pageView.height.takeIf { it > 0 } ?: context.resources.displayMetrics.heightPixels
)

}
} else {
CommonUtils.Companion.BitmapPool.recycleBitmap(bitmap)
}
}
}
Expand Down
Loading