开发过程中难免会遇到后台给返回的数据时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标签
}
........时间紧迫,本人就研究到此了