使用JSOUP将文档加载到WebView

时间:2015-08-18 13:39:27

标签: java android webview jsoup

我试图将网页的一部分解析为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()'在空对象引用上

2 个答案:

答案 0 :(得分:3)

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

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

  1. 您创建了一个应该下载并解析HTML的线程
  2. 您启动该主题并且可能会开始下载该页面
  3. 您设置了WebViewClient
  4. 您将数据加载到WebView并尝试访问element.html()(元素尚未初始化且仍为空)并获得空指针异常
  5. 之后,页面下载完成,element初始化
  6. 我建议你阅读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()

时为空