optimize webview
This commit is contained in:
+20
-24
@@ -2,13 +2,14 @@ package com.example.design_system
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableLongStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -21,8 +22,10 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import com.example.core.model.PrintEntity
|
||||
import com.example.design_system.util.PspJavaScriptInterface
|
||||
import com.example.design_system.util.WebViewManager
|
||||
import com.example.design_system.util.snackbar.SnackbarController
|
||||
import com.example.design_system.util.snackbar.SnackbarEvent
|
||||
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SuppressLint("JavascriptInterface")
|
||||
@@ -30,9 +33,7 @@ import kotlinx.coroutines.launch
|
||||
@Composable
|
||||
fun PspWebView(
|
||||
url: String,
|
||||
webView: WebView?,
|
||||
modifier: Modifier = Modifier,
|
||||
onWebView: (WebView) -> Unit,
|
||||
onPayClick: (amount: Long, id: String?) -> Unit,
|
||||
onDeviceInfo: () -> String,
|
||||
onPrintClick: (printEntities: List<PrintEntity>) -> Unit,
|
||||
@@ -42,7 +43,8 @@ fun PspWebView(
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var lastBackTime by remember { mutableLongStateOf(0L) }
|
||||
var isPaymentLaunching by remember { mutableStateOf(false) }
|
||||
var webView by remember { mutableStateOf<WebView?>(null) }
|
||||
|
||||
|
||||
// Use rememberUpdatedState to ensure the bridge always calls the latest callbacks
|
||||
val currentOnPayClick by rememberUpdatedState(onPayClick)
|
||||
@@ -69,7 +71,7 @@ fun PspWebView(
|
||||
scope.launch {
|
||||
SnackbarController.sendEvent(
|
||||
SnackbarEvent(
|
||||
message = "Press back again to exit"
|
||||
message = "برای خروج، دوباره بر روی بازگشت کلیک کنید."
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -77,42 +79,36 @@ fun PspWebView(
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
webView = WebViewManager.getWebView(context)
|
||||
onDispose {
|
||||
webView?.let { WebViewManager.releaseWebView(it) }
|
||||
}
|
||||
}
|
||||
|
||||
AndroidView(
|
||||
modifier = modifier,
|
||||
factory = { ctx ->
|
||||
WebView(ctx).apply {
|
||||
(webView ?: WebViewManager.getWebView(ctx)).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
overScrollMode = View.OVER_SCROLL_NEVER
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
canGoBack.value = view?.canGoBack() ?: false
|
||||
}
|
||||
}
|
||||
|
||||
settings.apply {
|
||||
javaScriptEnabled = true
|
||||
domStorageEnabled = true
|
||||
loadWithOverviewMode = true
|
||||
useWideViewPort = true
|
||||
cacheMode = WebSettings.LOAD_DEFAULT
|
||||
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
|
||||
|
||||
userAgentString =
|
||||
"Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 Chrome/120.0 Mobile Safari/537.36"
|
||||
}
|
||||
|
||||
|
||||
addJavascriptInterface(bridge, "NativeBridge")
|
||||
|
||||
|
||||
|
||||
loadUrl(url)
|
||||
onWebView(this)
|
||||
}
|
||||
},
|
||||
update = { view ->
|
||||
onWebView(view)
|
||||
update = {
|
||||
it.loadUrl(url)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.example.design_system.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import java.util.Stack
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object WebViewManager {
|
||||
|
||||
private const val POOL_SIZE = 1
|
||||
private val webViewPool = Stack<WebView>()
|
||||
|
||||
fun preload(context: Context) {
|
||||
if (webViewPool.isEmpty()) {
|
||||
repeat(POOL_SIZE) {
|
||||
val webView = createWebView(context)
|
||||
webViewPool.push(webView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getWebView(context: Context): WebView {
|
||||
return if (webViewPool.isNotEmpty()) {
|
||||
webViewPool.pop()
|
||||
} else {
|
||||
createWebView(context)
|
||||
}
|
||||
}
|
||||
|
||||
fun releaseWebView(webView: WebView) {
|
||||
if (webViewPool.size < POOL_SIZE) {
|
||||
webViewPool.push(webView)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private fun createWebView(context: Context): WebView {
|
||||
return WebView(context).apply {
|
||||
setLayerType(View.LAYER_TYPE_HARDWARE, null)
|
||||
settings.apply {
|
||||
javaScriptEnabled = true
|
||||
domStorageEnabled = true
|
||||
databaseEnabled = true
|
||||
cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
|
||||
loadsImagesAutomatically = true
|
||||
allowFileAccess = false
|
||||
useWideViewPort = true
|
||||
loadWithOverviewMode = true
|
||||
mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
||||
setSupportZoom(false)
|
||||
builtInZoomControls = false
|
||||
displayZoomControls = false
|
||||
userAgentString = "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 Chrome/120.0 Mobile Safari/537.36"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user