Kotlin WebView与JS交互报lateinit属性未初始化异常解决方案
异常根因
这个异常是WebAppInterface的实现逻辑错误导致的:
- 你在
WebAppInterface类中直接通过var mainActivity:MainActivity = MainActivity()手动实例化了一个全新的MainActivity对象。这个对象不是系统正常启动调度的Activity实例,不会走onCreate生命周期流程,内部的setWebviewDetails()方法从未被执行,myAndroidWebView这个lateinit修饰的属性始终没有被赋值。 - 当JS调用
showToast触发这个手动创建的无效MainActivity实例的testMessage方法时,访问未初始化的myAndroidWebView属性,就会抛出UninitializedPropertyAccessException。 - 附带的代码问题:你在
addJavascriptInterface时已经把真实运行的MainActivity实例作为Context传入了WebAppInterface,但完全没有使用这个有效实例,反而自己创建了无效的Activity对象;同时你在showToast中调用testMessage时传入了两个参数,但该方法本身只定义了一个字符串入参,本身也存在参数不匹配的编译问题。
修复方案
- 修改
WebAppInterface实现,不要手动创建MainActivity实例,直接通过构造函数持有真实的、已经完成初始化的MainActivity对象:
class WebAppInterface(private val mainActivity: MainActivity) { /** Show a toast from the web page */ @JavascriptInterface fun showToast(toast: String) { println("Interface call-1") mainActivity.testMessage(toast) } }
- 调整MainActivity中添加JS接口的代码,传入当前有效的MainActivity实例即可,其余WebView配置逻辑保持不变:
// setWebviewDetails方法中添加JS接口的代码替换为如下写法 myAndroidWebView.addJavascriptInterface(WebAppInterface(this), "AndroidApp")
额外优化建议
@JavascriptInterface注解标注的方法默认运行在WebView的后台子线程,不能直接操作UI,你当前用myAndroidWebView.post切回主线程执行JS调用的写法是可行的,也可以替换为runOnUiThread实现相同效果。- 直接拼接字符串到JS代码中存在注入风险,如果传入的字符串包含单引号、换行、特殊符号会导致JS执行报错,可以对传入的字符串做转义处理;Android 4.4+版本也可以使用
evaluateJavascript方法替代loadUrl执行JS,传参更安全,执行效率更高。
内容的提问来源于stack exchange,提问作者Vineesh TP
相关产品推荐
相关产品推荐

