Xamarin.Android中JavaScript调用Toast通知不显示问题求助
解决Xamarin.Android中JS回调时Toast不显示的问题
嘿,这个问题我太熟了!这绝对是线程上下文搞的鬼——你遇到的情况几乎可以肯定是JS接口的回调代码跑在了后台线程里,而Xamarin.Android要求所有UI操作(比如显示Toast)必须在UI线程执行。
问题根源
正常运行时,JS触发的C#回调方法默认是在后台线程执行的,直接在这个线程里调用Toast.Show()的话,UI系统根本不会处理这个请求;但当你设置断点时,线程被暂停,调试环境会临时把线程上下文切换到UI线程(或者说让Toast的代码意外在UI线程执行了),所以断点时Toast能正常显示。
解决方案:强制在UI线程执行Toast
你需要把Toast的显示代码包裹到UI线程的调度逻辑里,最常用的方式是用Activity的RunOnUiThread方法。具体步骤如下:
给CallJSInterface类传入Activity引用
首先修改你的接口类,让它持有当前Activity的弱引用(避免内存泄漏):class CallJSInterface : Java.Lang.Object { // 用弱引用持有Activity,防止内存泄漏 private readonly WeakReference<Activity> _weakActivity; public CallJSInterface(Activity activity) { _weakActivity = new WeakReference<Activity>(activity); } // 假设这是JS调用的导出完成回调方法 [JavascriptInterface] public void OnReportExportCompleted() { // 先确认Activity还存活 if (_weakActivity.TryGetTarget(out var currentActivity)) { // 把Toast操作调度到UI线程 currentActivity.RunOnUiThread(() => { Toast.MakeText(currentActivity, "报表导出完成!", ToastLength.Short).Show(); }); } } // 你的Timetable类和其他代码 private class Timetable { public string member { get; set; } // 其他属性... } }初始化CallJSInterface时传入Activity
在你的Activity里初始化WebView并绑定JS接口时,把当前Activity传进去:var jsInterface = new CallJSInterface(this); webView.AddJavascriptInterface(jsInterface, "AndroidInterface");
额外提醒
- 一定要用
WeakReference持有Activity,不然如果Activity被销毁(比如用户旋转屏幕),你的JS接口类还持有Activity的强引用,会导致严重的内存泄漏。 - 所有涉及UI的操作(比如更新TextView、显示Dialog)都必须遵循这个规则,只要是在非UI线程触发的,都要通过
RunOnUiThread或者Handler切换到UI线程执行。
内容的提问来源于stack exchange,提问作者Federico Navarrete
相关产品推荐
相关产品推荐

