Android WebView Fragment应用崩溃:NullPointerException问题求助
从你提供的崩溃日志和代码来看,问题的根源很明确:当Saying Fragment已经和MainActivity分离后,WebView的onPageStarted回调仍然尝试调用Activity的setUrl()方法,导致getActivity()返回null引发空指针异常。
为什么会出现这个问题?
当你通过fragmentTransaction.replace()切换Fragment时,原来的Saying Fragment会被从Activity的容器中移除,触发它的onDetach()等生命周期方法,此时Fragment不再依附于任何Activity。但WebView的加载任务可能还在后台运行,当加载开始时,onPageStarted回调被触发,这时候调用getActivity()就会返回null,强转后调用setUrl()自然就崩溃了。
具体解决方案
1. 先判断Activity是否存在再调用方法
最简单的临时修复是在调用setUrl()前先检查getActivity()是否不为null,并且是MainActivity的实例:
// 在Saying.java的onPageStarted方法里修改 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); // 先检查Activity是否有效 if (getActivity() != null && getActivity() instanceof MainActivity) { ((MainActivity) getActivity()).setUrl(url); } // 你的其他代码... }
2. 使用WeakReference持有Activity引用(更推荐)
为了避免内存泄漏同时保证调用安全,建议用WeakReference来持有Activity的引用:
// 在Saying Fragment类中添加成员变量 private WeakReference<MainActivity> mMainActivityRef; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); // 当Fragment依附到Activity时,保存弱引用 if (context instanceof MainActivity) { mMainActivityRef = new WeakReference<>((MainActivity) context); } } @Override public void onDetach() { super.onDetach(); // 当Fragment脱离Activity时,清空引用 if (mMainActivityRef != null) { mMainActivityRef.clear(); mMainActivityRef = null; } } // 然后修改onPageStarted方法 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); MainActivity activity = mMainActivityRef != null ? mMainActivityRef.get() : null; if (activity != null) { activity.setUrl(url); } // 你的其他代码... }
3. 在Fragment销毁时清理WebView回调
为了彻底避免Fragment销毁后还收到WebView的回调,建议在Fragment的onDestroyView方法中清理WebView的相关资源:
@Override public void onDestroyView() { super.onDestroyView(); // 假设你的WebView变量名为mWebView if (mWebView != null) { mWebView.stopLoading(); // 停止正在加载的任务 mWebView.setWebViewClient(null); // 移除WebViewClient回调 mWebView.setWebChromeClient(null); // 如果有WebChromeClient也一并移除 // 从父布局中移除WebView,避免内存泄漏 ViewParent parent = mWebView.getParent(); if (parent instanceof ViewGroup) { ((ViewGroup) parent).removeView(mWebView); } mWebView.destroy(); // 销毁WebView mWebView = null; } }
额外提醒
作为Android新手,要记住Fragment的生命周期和Activity是绑定的,当Fragment被replace、remove或者Activity销毁时,Fragment会脱离Activity,此时getActivity()就会返回null。任何在Fragment中调用Activity方法的地方,都要先做非空判断,避免空指针异常。
内容的提问来源于stack exchange,提问作者Noor Ali Khan

