如何强制 Android-WebView 立即重绘/重新渲染?

问题描述

基本上 JavascriptInterface 接收来自 WebView 的 Click 事件,然后我需要多次更改 HTML 元素,问题是 WebView 只显示最后一次更改,这意味着渲染不是立即的.

问题:如何使webview.loadUrl("javascript:updateProgress(20);");生效并立即更改WebView内容

- - - - - - - - - - - - - - - -

老问题:

我的 WebView 中有一个 HTML 进度条,我可以简单地通过从 webview.loadUrl("javascript:updateProgress(20);"); 运行 onCreate() 来更新进度条值。

// JavaScript in WebView
function updateProgress(percentage){

    document.getElementById('progressBar').style.width = percentage + '%';
}

现在,我有一个类可以将二进制数据发送到连接的 BLE 设备,我以 Google BluetoothLeGatt 中的示例为例,并在 BluetoothLeService.java添加一个写入特性(发送数据)的方法.

public void WriteCharacteristic(BluetoothGattCharacteristic characteristic,byte[] data,MainActivity mainactivity){

    byte[] data_twenty_byte = new byte [20];
    int progress_count = 0;

    while(get_next_twenty_byte(data,data_twenty_byte)){

        characteristic.setValue(data_twenty_byte);
        mBluetoothGatt.writeCharacteristic(characteristic);

        progress_count++;
        mainactivity.webview.loadUrl("javascript:updateProgress(" + progress_count + ");");
    }
}

问题是在 WriteCharacteristic() 运行时 WebView 不会更新(重绘/重新渲染),WebView 仅在 WriteCharacteristic() 之后重绘/重新渲染完成,表示进度条 100%。

注意:我已经尝试过 runOnUiThread(new Runnable() {});

我的问题是,如何强制 mainactivity.webview 立即重绘/重新渲染?

谢谢,

解决方法

如我的评论中所述,将长时间运行的进程推送到后台线程,然后在 ui 线程上运行 webview 更新应该可以实现您想要实现的目标。这是我拼凑的一个简单示例:

package com.example.myapplication

import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.JavascriptInterface
import android.webkit.WebView
import kotlin.concurrent.thread

class MainActivity : AppCompatActivity() {

    lateinit var webView: WebView

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        webView = WebView(this)
        webView.settings.javaScriptEnabled = true
        webView.addJavascriptInterface(this,"app")
        setContentView(webView)

        val html =
            """
            <html>
                <head>
                    <script type='text/javascript'>
                        function updateProgress(progress) {
                            let el = document.getElementById('progress');
                            el.innerText = progress;
                        }
                    </script>
                </head>
                <body>                    
                    <p>Value: <span id='progress'>0</span></p>
                    <button onclick='app.startUpdates();'>Start Update</button>
                </body>
            </html>            
            """.trimIndent()

        webView.loadData(html,"text/html","UTF-8")
    }

    @JavascriptInterface
    fun startUpdates() {
        doSomething()
    }

    private fun doSomething() {
        thread {
            for (i in 1..100) {
                runOnUiThread { webView.evaluateJavascript("updateProgress($i);",null) }
                Thread.sleep(10)
            }
        }
    }

}