Android中类似微博论坛中用ImageGetter异Html图片

来源:互联网 发布:mac app ui设计 编辑:程序博客网 时间:2024/06/06 19:19

在像微博、论坛等,往往需要显示富文本信息,其中一个常用的方法可能就是Android本身支持的Html标签所持有的方法Html.fromHtml(String);通过这个方法来自动解析String中的Html标签,来达到显示富文本的目的。那么我们来了解下

1、Html.fromHtml(String ,ImageGetter, TagHandler ) 来解析带有Html标签的字符串,参数3设为null即可或者直接Html.fromHtml(String ) 
2、如果需要对超链接、邮箱、电话等设置点击响应,则需要添加 setMovementMethod(LinkMovementMethod.getInstance())

下面来具体说下,fromHtml()第二个参数为ImageGetter,参数的意义在于处理富文本中的图片标签,也就是用于接收图片并返回图片。那么图片是哪来的呢,当然是网上,也就是我们需要进行下载图片的操作,每张图片通过网络获得字节流来进行保存或者处理显示等等。这里主要来看一下ImageGetter的写法,我们来看代码

public class HtmlImageGetter implements Html.ImageGetter {

private static final String TAG = "IMAGE_GETTER";

Activity context;
TextView textView;

public HtmlImageGetter(Activity context, TextView tv) {
this.context = context;
this.textView = tv;
}

@Override
public Drawable getDrawable(String source) {

// 1、取缓存
if (BaseApplication.getInstance().mTitleBitmaps.containsKey(source)) {
SoftReference<Bitmap> cacheBitmap = BaseApplication.getInstance().mTitleBitmaps
.get(source);
Bitmap softBitmap = null;
if (cacheBitmap != null) {
softBitmap = cacheBitmap.get();
Drawable softDrawable = new BitmapDrawable(softBitmap);
softDrawable.setBounds(getDefaultBitmapRounds(context));

return softDrawable;
}
}
// 2、取文件
String fileName = source.substring(source.lastIndexOf("/") + 1);
File file = new File(Constants.TEAM_CACHE_IMAGE + fileName);
if (file.exists()) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = false;
opts.inSampleSize = 2;

Bitmap fileBitmap = BitmapFactory.decodeFile(
Constants.TEAM_CACHE_IMAGE + fileName, opts);
Drawable fileDrawable = new BitmapDrawable(fileBitmap);
fileDrawable.setBounds(getDefaultBitmapRounds(context));

return fileDrawable;
}

// 3、取网络请求
URLDrawable uRLDrawable = new URLDrawable(context);
LoadImageAsync loadBitmap = new LoadImageAsync(uRLDrawable);
loadBitmap.execute(source, fileName);
return uRLDrawable;
}

/**
 * 图片保存到本地
 * 
 * @param in
 * @param dir
 * @param fileName
 * @throws IOException
 */
public void saveBitmap2File(InputStream in, String dirPath, String fileName)
throws IOException {

if (in == null) {
return;
}

if (dirPath == null || dirPath.equals("")) {
return;
}

if (fileName == null || fileName.equals("")) {
return;
}

if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return;
}

File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}

File file = new File(dirPath + fileName);
if (!file.exists()) {
file.createNewFile();
}

OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length = -1;

while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}

out.flush();
out.close();
}
       //网络下载图片
public class LoadImageAsync extends AsyncTask<String, Void, Drawable> {

URLDrawable mUrlDrawable;

public LoadImageAsync(URLDrawable mUrlDrawable) {
this.mUrlDrawable = mUrlDrawable;
}

@Override
protected Drawable doInBackground(String... arg0) {

String url = arg0[0];
String fileName = arg0[1];

URL Url;
Drawable drawable = null;
try {
Url = new URL(url);
InputStream in = Url.openStream();
// 保存到文件
saveBitmap2File(in, Constants.TEAM_CACHE_IMAGE, fileName);
in.close();

File file = new File(Constants.TEAM_CACHE_IMAGE + fileName);
if (file.exists()) {
Bitmap bitmap = BitmapManager.decodeSampledBitmapFromFile(
Constants.TEAM_CACHE_IMAGE + fileName, 480, 800);
// 保存到缓存
if (!BaseApplication.getInstance().mTitleBitmaps
.containsKey(url)) {
BaseApplication.getInstance().mTitleBitmaps.put(url,
new SoftReference<Bitmap>(bitmap));
}

drawable = new BitmapDrawable(bitmap);
drawable.setBounds(getDefaultBitmapRounds(context));
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return drawable;
}

@Override
protected void onPostExecute(Drawable result) {

if (result != null) {
mUrlDrawable.drawable = result;
HtmlImageGetter.this.textView.requestLayout();
}
}
}
       
public class URLDrawable extends BitmapDrawable {

protected Drawable drawable;

public URLDrawable(Context context) {
this.setBounds(getDefaultBitmapRounds(context));
drawable = context.getResources().getDrawable(
R.drawable.default_news);
drawable.setBounds(getDefaultBitmapRounds(context));
}

@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (drawable != null) {
drawable.draw(canvas);
}
}
}
        //图片显示大小
public Rect getDefaultBitmapRounds(Context context) {

return new Rect(0, 0,
ScreenManager.getScreenWidth((Activity) context) / 2,
ScreenManager.getScreenWidth((Activity) context) * 3 / 4);
}

}

以上是完整的ImageGetter的代码,那么这里来解释一下;
首先,整个代码分为3个类:
(1)主类 HtmlImageGetter需要继承Html.ImageGetter;这里需要重写一个方法getDrawable(String url),从字面上看就是得到Drawable图片,也就是我们要显示的图片,从这里我们明白了,得到图片的操作要写在getDrawable()中,方法的参数url,也就是资源的位置,即下载地址,具体来说就是Html标签中的<img>标签里的网络地址,下载也是基于这个地址的。
(2)子类LoadImageAsync,一看就知道这是一个异步加载图片的AsyncTask类,我们用他来实现异步加载。那么为什么异步加载呢?我们想象一下ListView中会有多少Item,如果每个Item都有一张Image,我们的程序也就崩溃的不能再崩溃了,所以异步加载是保证正常运行甚至用户体验必须的操作。
(3)子类URLDrawable ,这个类的作用就是我们在加载图片的时候可以设置一张默认显示的图片,然后加载完成的同时进行替换,这样有利于良好的用户体验。

        其次,看构造我们可以看到,传入了一个TextView,那么为什么呢?试想,如果单纯在getDrawable中开启线程的话,下载完成后我们如何将线程的Drawable作为返回值供getDrawable返回呢,答案很显然是否定的。我们的做法是先返回一个null,也就是显示默认图片,等下载完成后通过刷新布局来显示Html图片;所以textview的作用就是用来刷新布局。

       然后先来看AsyncTask部分,这个类主要实现下载网络图片的功能;里面的内容很简单:
首先1、下载图片,也就是打开连接得到字节流  2、保存图片到本地  3、从本地取出该图片,并保存到缓存(软引用序列) 4、处理返回
       首先下载图片,getDrawavle的参数是下载地址,将他传入AsyncTask,打开连接得到字节流,然后将流保存到本地。这里应该不同解释了。这里采用的过程是先保存到本地,再从本地取出图片,而不是直接将流解析成图片返回;因为后者需要两次打开流,浪费资源。从本地取出该图片,在处理之前需要先保存到软引用的缓存队列,这里我把这个Map存到Application的基层类中,避免数次重置。从本地读取的时候要注意我们只需要缩略图即可,节省内存也防止OOM.之后是图片的处理返回,注意的是一定要设置setBounds(),否则不显示; OnPOST中刷新一下布局来显示下载的图片

再来看getDrawable中的逻辑,首先读取缓存的图片,缓存是最快的,然后没有的话读取本地文件,最后是网络下载,一般都是这么处理,不多作解释了,还要注意设定显示大小setBounds(),以及取出图片的时候压缩取缩略图即可满足我们的要求。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 丈夫去世了婆婆不喜欢儿媳妇怎么办 高考看不下去书怎么办 在东莞读书读不成高中怎么办 嗓子哑了怎么办土方法 小孩舌头太长太大讲话不清楚怎么办 一周岁不喝奶粉怎么办 一岁的宝宝不吃奶粉怎么办 小孩不爱吃饭怎么办吃什么药 小孩这几天不爱吃饭怎么办 宝宝这几天不爱吃饭怎么办 想看书看不进去怎么办 宝宝3岁不爱看书怎么办 4岁宝宝不爱看书怎么办 1岁宝宝不爱看书怎么办 孩子一看书就哭怎么办 我不想读大专了怎么办 一年级的小孩不爱学习怎么办 高中的孩子不爱学习怎么办 9个月宝宝肠胃不好怎么办 孩子高烧过后干呕不爱吃饭怎么办 母乳涨奶发烧了怎么办 涨奶发烧了怎么办啊 2岁宝贝不吃饭怎么办 4个月的婴儿厌食怎么办 2个月婴儿厌食怎么办 3个月宝宝厌奶怎么办 没胃口吃不下饭怎么办 小孩吃多了积食怎么办 孩子吃撑了难受怎么办 卵巢早衰月经量少怎么办 7岁孩吃饭少消瘦怎么办 宝宝3岁不吃饭怎么办 小孩吃多了吐了怎么办 6岁儿童越来越瘦怎么办 7岁儿童不吃饭怎么办 天热宝宝不好好吃饭怎么办 天热宝宝不爱吃饭怎么办 天热宝宝不想吃饭怎么办 夏天天热宝宝不爱吃饭怎么办 3岁宝宝吃饭不香怎么办 胃ca吃饭反胃没食欲怎么办