使用JSOUP将文档加载到WebView

我正在尝试将网页的一部分解析为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 ba"); } 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()’

您的问题是您正在使用线程下载并解析HTML内容(这是正确的事情),然后您尝试从线程外部的Element对象加载。 因为下载页面需要一些时间才能完成,所以在初始化之前调用element.html()因此为null – 这就是你得到NullPointerException的原因。

为了解释发生了什么,让我们看一下loadArticleWithHtml方法的流程:

  1. 您创建了一个应该下载和解析HTML的线程
  2. 您启动该线程,可能会开始下载页面
  3. 您设置WebViewClient
  4. 您将数据加载到WebView并尝试访问element.html() (元素尚未初始化并仍为null)并获得空指针exception
  5. 之后,页面下载完成, element初始化

我建议你阅读更多有关线程的信息 。 当您使用线程时,该进程与UI线程(您正在加载HTML的位置)并行运行,并且无法保证在UI线程中的其余代码完成之前完成。 事实上,在UI线程上工作并在其中间启动一个线程,几乎可以保证线程将在UI代码完成后完成,如果代码执行任何缓慢的下载操作。

因此,解决方案是正确地线程化您的应用程序并在线程内初始化元素变量之后加载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 ba"); } 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线程上运行代码的其他信息,请参阅此Q / A.

我想你不知道这个事实

 doc.select("#mp-itn ba") 

尽管在CSS选择器中使用了# ,它实际上只返回一个Element,但它将返回Elements,即匹配的Element节点的集合。 如果你使用

 doc.select("#mp-itn ba").first() 

它至少会获得你想要的id元素。 也许你的代码有更多的问题,我没有检查。

附录

我对Android开发不是很熟悉,但是你得到的错误指向空指针问题,指示在尝试调用element.html()地方element为null