我试图将网页的一部分解析为WebView。我使用jsoup库来获取我需要的页面的一部分,然后加载到webview。 这是代码:
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();
}
}
};
downloadThread.start();
mWebView.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), description, Toast.LENGTH_SHORT).show();
}
});
try {
mWebView.loadData(element.html(), "text/html", "UTF-8");
} catch (NullPointerException e){
e.printStackTrace();
Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_LONG).show();
}
}
但我总是收到错误
尝试调用虚方法' java.lang.String org.jsoup.select.Elements.html()'在空对象引用上
答案 0 :(得分:3)
您的问题是您正在使用线程下载并解析HTML内容(这是正确的事情),然后您尝试从线程的外部加载元素对象。因为下载页面需要一些时间才能完成,所以在初始化之前调用element.html()
因此为空 - 这就是你得到NullPointerException的原因。
为了解释发生了什么,让我们看一下loadArticleWithHtml
方法的流程:
element.html()
(元素尚未初始化且仍为空)并获得空指针异常element
初始化我建议你阅读more about threading。当您使用线程时,该进程与UI线程(您正在加载HTML的位置)并行运行,并且不保证在UI线程中的其余代码执行之前完成。实际上,在UI线程上工作并在其中间启动一个线程,几乎可以保证线程将在UI代码完成后完成,如果代码执行任何缓慢的下载等操作。
因此,解决方案是正确地线程化您的应用程序并加载WebView AFTER 元素变量已从线程中初始化。见下文。
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方法,因为它是一个视图,应该从主线程访问。有关在UI线程上运行代码的其他信息,请参阅this Q/A。
答案 1 :(得分:0)
我认为你不知道这个事实
doc.select("#mp-itn b a")
将返回Elements,即匹配的Element节点的集合,尽管在CSS选择器中使用了#
,它实际上只返回一个Element。如果你使用
doc.select("#mp-itn b a").first()
它至少会获得你想要的id元素。也许你的代码存在更多问题,我没有检查过。
<强>附录强>
我对Android开发不是很熟悉,但是你得到的错误指向空指针问题,表示element
在您尝试调用element.html()