loadUrl 方法的长度限制
-
在 Android WebView 开发中,使用 loadUrl 方法执行 Iavascript 代码并传递数据时,数据长度是受到限制的
-
数据长度通常被限制为不能超过 2MB
loadUrl 方法的长度限制演示
1、准备阶段
(1)Web
- loadUrl.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>loadUrl</title>
</head>
<body>
<script>
function printContentLength(content) {
console.log("----- ", content.length);
}
</script>
</body>
</html>
(2)Activity Layout
- activity_load_url.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoadUrlActivity"
tools:ignore="MissingConstraints">
<WebView
android:id="@+id/wv_container"
android:layout_width="match_parent"
android:layout_height="500dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(3)Activity Code
- LoadUrlActivity.java
java
public class LoadUrlActivity extends AppCompatActivity {
public static final String TAG = LoadUrlActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_url);
WebView wvContainer = findViewById(R.id.wv_container);
wvContainer.loadUrl("file:///android_asset/webview/loadUrl.html");
WebSettings webSettings = wvContainer.getSettings();
webSettings.setJavaScriptEnabled(true);
wvContainer.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
wvContainer.loadUrl("javascript:printContentLength('hello world')");
}
});
}
}
2、测试记录
- 传递长度为 1MB 的数据
java
String str = new String(new char[1024 * 1024]).replace("\0", "a");
wvContainer.loadUrl("javascript:printContentLength('" + str + "')");
# 输出结果
----- 1048576
- 传递长度为 2MB 的数据
java
String str = new String(new char[2 * 1024 * 1024]).replace("\0", "a");
wvContainer.loadUrl("javascript:printContentLength('" + str + "')");
# 输出结果
(无)
优化方案
1、基本介绍
-
优先使用 evaluateJavascript 方法来执行 JavaScript 代码,它没有字符数限制,执行效率更高,并能获取 JavaScript 的返回值
-
如果仍然使用 loadUrl 方法来执行较长的 JavaScript 代码,可以分片传输数据
2、演示
(1)使用 evaluateJavascript 方法
- 传递长度为 1MB 的数据
java
String str = new String(new char[1024 * 1024]).replace("\0", "a");
wvContainer.evaluateJavascript("printContentLength('" + str + "')", null);
# 输出结果
----- 1048576
- 传递长度为 2MB 的数据
java
String str = new String(new char[2 * 1024 * 1024]).replace("\0", "a");
wvContainer.evaluateJavascript("printContentLength('" + str + "')", null);
# 输出结果
----- 2097152
(2)分片传输数据
- 传递长度为 2MB 的数据
js
let contents = null;
function printContentLength(content, chunkNum, chunkTotal) {
if (contents == null) contents = [];
contents.push(content);
if (chunkNum != chunkTotal) return;
console.log("----- ", contents.join("").length);
}
java
String str = new String(new char[2 * 1024 * 1024]).replace("\0", "a");
// 分片传输字符串
int chunkSize = 1024 * 1024; // 1MB 分片
int chunkTotal = (int) Math.ceil((double) str.length() / chunkSize);
for (int i = 0; i < chunkTotal; i++) {
int start = i * chunkSize;
int end = Math.min(start + chunkSize, str.length());
String chunk = str.substring(start, end);
wvContainer.loadUrl(String.format("javascript:printContentLength('%s', %d, %d)",
chunk, i + 1, chunkTotal));
}
# 输出结果
----- 2097152