您的问题是您正在使用线程下载并解析 HTML 内容(这是正确的做法),然后您尝试从 Element 对象加载outside线程。由于下载页面需要一些时间才能完成,因此您正在调用element.html()
在它被初始化之前,因此为空 - 这就是为什么你会得到一个 NullPointerException。
为了解释发生了什么,让我们看看你的流程loadArticleWithHtml
method:
- 您创建一个应该下载并解析 HTML 的线程
- 您启动线程,页面的下载可能会开始
- 您设置 WebViewClient
- 您将数据加载到 WebView 中并尝试访问
element.html()
(元素还没有初始化,仍然为空)并得到空指针异常
- 一段时间后,页面下载完成并
element
已初始化
我建议你阅读有关线程的更多信息。当您使用线程时,该进程与 UI 线程(您正在加载 HTML 的位置)并行运行,并且不能保证在 UI 线程中的其余代码完成之前完成。事实上,在 UI 线程上工作并在其中启动一个线程,如果代码正在执行诸如下载之类的缓慢操作,则几乎可以保证该线程将在 UI 代码完成后完成。
因此,解决方案是正确地对应用程序进行线程化并加载 WebViewAFTER元素变量已在线程内初始化。见下文。
public void loadArticleWithHTML (){
Thread downloadThread = new Thread() {
public void run() {
try {
doc = Jsoup.connect("http://en.wikipedia.org/").get();
element = doc.select("#mp-itn b a");
} catch (java.io.IOException e){
e.printStackTrace();
}
if (element == null) {
Log.e("error", "There is a problem with the selection");
} else {
// post a new Runnable from a Handler in order to run the WebView loading code from the UI thread
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
mWebView.loadData(element.html(), "text/html", "UTF-8");
}
});
}
}
};
mWebView.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), description, Toast.LENGTH_SHORT).show();
}
});
downloadThread.start();
}
请注意,您需要从 UI 线程运行 WebView 方法,因为它是一个视图,应该从主线程访问。看this Q/A有关在 UI 线程上运行代码的更多信息。