优化
This commit is contained in:
@@ -90,7 +90,7 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|||||||
* 存储异常和参数信息
|
* 存储异常和参数信息
|
||||||
*/
|
*/
|
||||||
private val paramsMap by lazy {
|
private val paramsMap by lazy {
|
||||||
val map = HashMap<String, String>()
|
val map = LinkedHashMap<String, String>()
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
//获取系统信息
|
//获取系统信息
|
||||||
map["MANUFACTURER"] = Build.MANUFACTURER
|
map["MANUFACTURER"] = Build.MANUFACTURER
|
||||||
@@ -104,6 +104,7 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|||||||
e.toString()
|
e.toString()
|
||||||
}
|
}
|
||||||
map["packageName"] = appCtx.packageName
|
map["packageName"] = appCtx.packageName
|
||||||
|
map["heapSize"] = Runtime.getRuntime().maxMemory().toString()
|
||||||
//获取app版本信息
|
//获取app版本信息
|
||||||
AppConst.appInfo.let {
|
AppConst.appInfo.let {
|
||||||
map["versionName"] = it.versionName
|
map["versionName"] = it.versionName
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import io.legado.app.BuildConfig
|
|||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
|
import io.legado.app.utils.canvasrecorder.CanvasRecorderFactory
|
||||||
import io.legado.app.utils.getPrefBoolean
|
import io.legado.app.utils.getPrefBoolean
|
||||||
import io.legado.app.utils.getPrefInt
|
import io.legado.app.utils.getPrefInt
|
||||||
import io.legado.app.utils.getPrefLong
|
import io.legado.app.utils.getPrefLong
|
||||||
@@ -37,7 +38,8 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
|||||||
var clickActionBR = appCtx.getPrefInt(PreferKey.clickActionBR, 1)
|
var clickActionBR = appCtx.getPrefInt(PreferKey.clickActionBR, 1)
|
||||||
var themeMode = appCtx.getPrefString(PreferKey.themeMode, "0")
|
var themeMode = appCtx.getPrefString(PreferKey.themeMode, "0")
|
||||||
var useDefaultCover = appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
var useDefaultCover = appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
||||||
var optimizeRender = appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
var optimizeRender = CanvasRecorderFactory.isSupport
|
||||||
|
&& appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
||||||
var recordLog = appCtx.getPrefBoolean(PreferKey.recordLog)
|
var recordLog = appCtx.getPrefBoolean(PreferKey.recordLog)
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
@@ -87,8 +89,8 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
|||||||
PreferKey.useDefaultCover -> useDefaultCover =
|
PreferKey.useDefaultCover -> useDefaultCover =
|
||||||
appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
||||||
|
|
||||||
PreferKey.optimizeRender -> optimizeRender =
|
PreferKey.optimizeRender -> optimizeRender = CanvasRecorderFactory.isSupport
|
||||||
appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
&& appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
||||||
|
|
||||||
PreferKey.recordLog -> recordLog = appCtx.getPrefBoolean(PreferKey.recordLog)
|
PreferKey.recordLog -> recordLog = appCtx.getPrefBoolean(PreferKey.recordLog)
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ import io.legado.app.model.ReadBook
|
|||||||
import io.legado.app.ui.book.read.ReadBookActivity
|
import io.legado.app.ui.book.read.ReadBookActivity
|
||||||
import io.legado.app.ui.book.read.page.provider.ChapterProvider
|
import io.legado.app.ui.book.read.page.provider.ChapterProvider
|
||||||
import io.legado.app.ui.widget.number.NumberPickerDialog
|
import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||||
|
import io.legado.app.utils.canvasrecorder.CanvasRecorderFactory
|
||||||
import io.legado.app.utils.dpToPx
|
import io.legado.app.utils.dpToPx
|
||||||
import io.legado.app.utils.getPrefBoolean
|
import io.legado.app.utils.getPrefBoolean
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
|
import io.legado.app.utils.removePref
|
||||||
import io.legado.app.utils.setEdgeEffectColor
|
import io.legado.app.utils.setEdgeEffectColor
|
||||||
|
|
||||||
class MoreConfigDialog : BasePrefDialogFragment() {
|
class MoreConfigDialog : BasePrefDialogFragment() {
|
||||||
@@ -83,6 +85,10 @@ class MoreConfigDialog : BasePrefDialogFragment() {
|
|||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
addPreferencesFromResource(R.xml.pref_config_read)
|
addPreferencesFromResource(R.xml.pref_config_read)
|
||||||
upPreferenceSummary(PreferKey.pageTouchSlop, slopSquare.toString())
|
upPreferenceSummary(PreferKey.pageTouchSlop, slopSquare.toString())
|
||||||
|
if (!CanvasRecorderFactory.isSupport) {
|
||||||
|
removePref(PreferKey.optimizeRender)
|
||||||
|
preferenceScreen.removePreferenceRecursively(PreferKey.optimizeRender)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import io.legado.app.ui.book.read.page.provider.ChapterProvider
|
|||||||
import io.legado.app.ui.book.read.page.provider.LayoutProgressListener
|
import io.legado.app.ui.book.read.page.provider.LayoutProgressListener
|
||||||
import io.legado.app.ui.book.read.page.provider.TextPageFactory
|
import io.legado.app.ui.book.read.page.provider.TextPageFactory
|
||||||
import io.legado.app.utils.activity
|
import io.legado.app.utils.activity
|
||||||
import io.legado.app.utils.canvasrecorder.pools.BitmapPool
|
|
||||||
import io.legado.app.utils.invisible
|
import io.legado.app.utils.invisible
|
||||||
import io.legado.app.utils.longToastOnUi
|
import io.legado.app.utils.longToastOnUi
|
||||||
import io.legado.app.utils.showDialogFragment
|
import io.legado.app.utils.showDialogFragment
|
||||||
@@ -485,7 +484,6 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
|||||||
pageDelegate?.onDestroy()
|
pageDelegate?.onDestroy()
|
||||||
curPage.cancelSelect()
|
curPage.cancelSelect()
|
||||||
invalidateTextPage()
|
invalidateTextPage()
|
||||||
BitmapPool.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ object LogUtils {
|
|||||||
}
|
}
|
||||||
append("WebViewUserAgent=").append(userAgent).append("\n")
|
append("WebViewUserAgent=").append(userAgent).append("\n")
|
||||||
append("packageName=").append(appCtx.packageName).append("\n")
|
append("packageName=").append(appCtx.packageName).append("\n")
|
||||||
|
append("heapSize=").append(Runtime.getRuntime().maxMemory()).append("\n")
|
||||||
//获取app版本信息
|
//获取app版本信息
|
||||||
AppConst.appInfo.let {
|
AppConst.appInfo.let {
|
||||||
append("versionName=").append(it.versionName).append("\n")
|
append("versionName=").append(it.versionName).append("\n")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ object CanvasRecorderFactory {
|
|||||||
|
|
||||||
private val atLeastApi24 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
private val atLeastApi24 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
||||||
private val atLeastApi29 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
private val atLeastApi29 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||||
|
val isSupport = atLeastApi24
|
||||||
|
|
||||||
// issue 3868
|
// issue 3868
|
||||||
fun create(locked: Boolean = false): CanvasRecorder {
|
fun create(locked: Boolean = false): CanvasRecorder {
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package io.legado.app.utils.canvasrecorder
|
|||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import io.legado.app.utils.canvasrecorder.pools.BitmapPool
|
import com.bumptech.glide.Glide
|
||||||
import io.legado.app.utils.canvasrecorder.pools.CanvasPool
|
import io.legado.app.utils.canvasrecorder.pools.CanvasPool
|
||||||
|
import splitties.init.appCtx
|
||||||
|
|
||||||
class CanvasRecorderImpl : BaseCanvasRecorder() {
|
class CanvasRecorderImpl : BaseCanvasRecorder() {
|
||||||
|
|
||||||
@@ -19,14 +20,14 @@ class CanvasRecorderImpl : BaseCanvasRecorder() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
bitmap = BitmapPool.obtain(width, height)
|
bitmap = bitmapPool.get(width, height, Bitmap.Config.ARGB_8888)
|
||||||
}
|
}
|
||||||
if (bitmap!!.width != width || bitmap!!.height != height) {
|
if (bitmap!!.width != width || bitmap!!.height != height) {
|
||||||
if (canReconfigure(width, height)) {
|
if (bitmap!!.isMutable && canReconfigure(width, height)) {
|
||||||
bitmap!!.reconfigure(width, height, Bitmap.Config.ARGB_8888)
|
bitmap!!.reconfigure(width, height, Bitmap.Config.ARGB_8888)
|
||||||
} else {
|
} else {
|
||||||
BitmapPool.recycle(bitmap!!)
|
bitmapPool.put(bitmap!!)
|
||||||
bitmap = BitmapPool.obtain(width, height)
|
bitmap = bitmapPool.get(width, height, Bitmap.Config.ARGB_8888)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,12 +58,13 @@ class CanvasRecorderImpl : BaseCanvasRecorder() {
|
|||||||
override fun recycle() {
|
override fun recycle() {
|
||||||
super.recycle()
|
super.recycle()
|
||||||
val bitmap = bitmap ?: return
|
val bitmap = bitmap ?: return
|
||||||
BitmapPool.recycle(bitmap)
|
bitmapPool.put(bitmap)
|
||||||
this.bitmap = null
|
this.bitmap = null
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val canvasPool = CanvasPool(2)
|
private val canvasPool = CanvasPool(2)
|
||||||
|
private val bitmapPool = Glide.get(appCtx).bitmapPool
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
package io.legado.app.utils.canvasrecorder.pools
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import io.legado.app.help.globalExecutor
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
object BitmapPool {
|
|
||||||
|
|
||||||
private val reusableBitmaps: MutableSet<Bitmap> = ConcurrentHashMap.newKeySet()
|
|
||||||
|
|
||||||
fun recycle(bitmap: Bitmap) {
|
|
||||||
reusableBitmaps.add(bitmap)
|
|
||||||
trimSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
if (reusableBitmaps.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
globalExecutor.execute {
|
|
||||||
val iterator = reusableBitmaps.iterator()
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
val item = iterator.next()
|
|
||||||
iterator.remove()
|
|
||||||
item.recycle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun trimSize() {
|
|
||||||
globalExecutor.execute {
|
|
||||||
var byteCount = 0
|
|
||||||
val iterator = reusableBitmaps.iterator()
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
val item = iterator.next()
|
|
||||||
if (byteCount > 64 * 1024 * 1024) {
|
|
||||||
iterator.remove()
|
|
||||||
item.recycle()
|
|
||||||
} else {
|
|
||||||
byteCount += item.byteCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun obtain(width: Int, height: Int): Bitmap {
|
|
||||||
if (reusableBitmaps.isEmpty()) {
|
|
||||||
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
||||||
}
|
|
||||||
val iterator = reusableBitmaps.iterator()
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
val item = iterator.next()
|
|
||||||
if (item.isMutable) {
|
|
||||||
// Check to see it the item can be used for inBitmap.
|
|
||||||
if (canReconfigure(item, width, height)) {
|
|
||||||
// Remove from reusable set so it can't be used again.
|
|
||||||
iterator.remove()
|
|
||||||
item.reconfigure(width, height, Bitmap.Config.ARGB_8888)
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Remove from the set if the reference has been cleared.
|
|
||||||
iterator.remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun canReconfigure(
|
|
||||||
candidate: Bitmap,
|
|
||||||
width: Int,
|
|
||||||
height: Int
|
|
||||||
): Boolean {
|
|
||||||
// From Android 4.4 (KitKat) onward we can re-use if the byte size of
|
|
||||||
// the new bitmap is smaller than the reusable bitmap candidate
|
|
||||||
// allocation byte count.
|
|
||||||
val byteCount: Int = width * height * getBytesPerPixel(candidate.config)
|
|
||||||
return byteCount <= candidate.allocationByteCount
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A helper function to return the byte usage per pixel of a bitmap based on its configuration.
|
|
||||||
*/
|
|
||||||
private fun getBytesPerPixel(config: Bitmap.Config?): Int {
|
|
||||||
return when (config) {
|
|
||||||
Bitmap.Config.ARGB_8888 -> 4
|
|
||||||
Bitmap.Config.RGB_565, Bitmap.Config.ARGB_4444 -> 2
|
|
||||||
Bitmap.Config.ALPHA_8 -> 1
|
|
||||||
else -> 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user