Android解析html文件的两种方案以及对比

         开发过程中难免会遇到后台给返回的数据时html格式的数据,确实是第一反应就是一脸蒙蔽,给我返回html干甚,不过为了便于部分模块的拓展、修改,还是用html比较好,没办法来吧,解析处理吧。

         方案一:TextView来处理html内容

    /**
     * 加载html内容
     */
    public void loadHtmlText(final TextView textView, final String html) {
        textView.post(new Runnable() {
            @Override
            public void run() {
                final int screenWidth = textView.getMeasuredWidth();
                final Message msg = Message.obtain();
                msg.obj = textView;
                final Bundle bundle = new Bundle();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Spanned spanned = Html.fromHtml(html, new Html.ImageGetter() {
                            @Override
                            public Drawable getDrawable(String source) {
                                InputStream is = null;
                                try {
                                    is = (InputStream) new URL(source.replace("https", "http")).getContent();
                                    Drawable dra = Drawable.createFromStream(is, "src");
                                    int i = dra.getIntrinsicWidth() * 13;
                                    int i1 = dra.getIntrinsicHeight() * 13;
                                    dra.setBounds(0, 0, i, i1);
                                    if (i > screenWidth & i1 != 0) {
                                        float i2 = (float) i / i1;
                                        dra.setBounds(0, 0, screenWidth, (int) (screenWidth / i2));
                                    }
                                    return dra;
                                } catch (MalformedURLException e) {
                                    return null;
                                } catch (IOException e) {
                                    return null;
                                } finally {
                                    try {
                                        if (null != is) {
                                            is.close();
                                        }
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }, null);
                        if (null != mHandler) {
                            bundle.putCharSequence("data", spanned);
                            msg.setData(bundle);
                            mHandler.sendMessage(msg);
                        }
                    }
                }).start();
            }
        });
    }
   private Handler mHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            CharSequence c= (CharSequence) msg.getData().get("data");
            TextView textView= (TextView) msg.obj;
            textView.setText(c);
        }
    };

    上面的代码已经可以实现加载html内容了,并且加载后的内容、图片会根据控件大小进行缩小显示,看似很完美,但是存在如下注意点和缺点

     1.加载的过程必须要放到子线程中去

     2.页面关闭的时候handler必须要销毁,防止内存泄露

     3.这样加载显示适用于那些内容不多、图片不大的情况下,如果图片特别多,那么很不幸容易出现oom问题

     4.如果html内容中标签不是那么规范,比如说缺少一个标签,但是浏览器可以正常显示,而这么解析会出现显示代码的情况

基于以上问题,我们提出了方案二。

     方案二:使用webview去解析加载

        mWebView = new WebView(mContext.getApplicationContext());
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.setMargins(AutoUtils.getPercentWidthSize(6), AutoUtils.getPercentHeightSize(6), AutoUtils.getPercentWidthSize(10), 0);
        mLlSuveryHolder.addView(mWebView, params);
        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.setHorizontalScrollBarEnabled(false);//水平不显示
        mWebView.setVerticalScrollBarEnabled(false); //垂直不显示
        mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);//硬件加速
       mWebView.loadDataWithBaseURL("", "html", "text/html", "utf-8", "");
                

        好了,初步加载就是上面的这个代码,但是会有问题:

      1.如果html中有超链接,点击会进行跳转,那就悲剧了,所以要将超链接禁掉

   mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                view.loadUrl("javascript: var allLinks = document.getElementsByTagName('a'); if (allLinks) {var i;for (i=0; i<allLinks.length; i++) {var link = allLinks[i];var target = link.getAttribute('target'); if (target) {link.setAttribute('target','');link.href = 'newtab:'+link.href;}}}if(false);");
            }

            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return true;
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return true;
            }
        });

     2.如果html中加载的图片特别大,也就是说没有像h5页面一样对手机进行了适配,那么页面会特别大,不是刚好显示控件这么大需要处理,百度有人给了一段代码,加载html内容前面一起去加载:

    String css_style = "<head><style>img{max-width:330px !important;}</style></head>";
    mWebView.loadDataWithBaseURL("", css_style +"html", "text/html", "utf-8", "");
              

    加上这段代码之后,却是在我的手机上很完美,但是一看他写了一个330px就知道,肯定不对,怎么能都写死呢,这个值肯定和手机有关、和显示的控件大小有关系,经过研究后330px替换为:

 DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
 float density = dm.density;
 控件的宽度/density-8

   这里的8确切说也是不对的,不过经过几台手机测试验证后基本上满足需求。

     3.在安卓4.3的模拟器和真机上出现一个奇葩现象,就是第一个页面加载显示正常,但是第二次开始就显示空白页,解决如下:

     activity的tofinish方法之前调用如下方法:

        if (mWebView != null) {
            mWebView.clearHistory();
            mWebView.loadUrl("about:blank");
            mWebView.stopLoading();
            mWebView.setWebChromeClient(null);
            mWebView.setWebViewClient(null);
            ((ViewGroup) mWebView.getParent()).removeView(mWebView);
            mWebView.destroy();
            mWebView = null;
            System.gc();
        }

其实就是释放webview,进行释放。

      4.优缺点:相比于textview去加载,内存会大大减小,约为textview的1/4,但是需要注意webview的使用

       方案三:提取img标签,自己去加载再设置回html页面中

      其实这个确实是一个方案,而且在ios端已经应用成功了,但是安卓端到目前为止也没有应用的,思路如下:

       1)遍历html中所有的标签,提取出img标签,并在相应的为止做好标记,暂时替换为显示本地默认图片

       2)用glide的联网框架加载提取出来的图片,保存到本地,下次直接读取

       3)将加载完的图片根据标记设置回去相应的位置

     这里本人也做了一些工作:

      1)提取标签,用jsoup去解析html内容

       第一:build.gradle文件中加入:

   compile 'org.jsoup:jsoup:1.10.2'

      注意混淆的时候加上  -keep class org.jsoup

       第二:代码中查找img标签 

       Document doc= Jsoup.parse(htmltext);
            Elements elements=doc.getElementsByTag("img");
            for (Element element : elements) {
                //element 就是img标签
       }
   ........时间紧迫,本人就研究到此了


     


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值