android 视频的缩略图 缓存机制和 异步加载缩略图
在这次的工作开发项目中,涉及到一个视频缩略图的视频列表;这个在大家看来,制作视频缩略图就是两行代码就搞定的事。确实是这样的,百度一下,每个帖子都知道制作视频缩略图的方法,在这里确实也是一样的,但是我要实现的是让缩略图 在ListView上显示,而且不会出现卡顿,其实也不是特别难,确实很实用;
主要的实现机制就是 异步加载 和 缓存机制 在加上一个绑定TAG机制;接下来就开始去实现吧
先上我的是 结构图:

这个包结构的 自定义 ListView 实现了 仿手机联系人按一定的数据分类 功能,和浮动组标题效果,但是这些功能都不是我今天要强调的,这里只说 怎么样实现缩略图的缓存机制,所以重要的的事 MyVideoThumbLoader类,
简略的的介绍下其他类:
VideoBean 是视频的实体类,用来存储视频数据,包括 视频路径,文件名,时长,。。。做过项目的都懂
VideoUtil 是工具类,写了一些基本的查找视频文件的方法,和创建缩略图的方法
MyPinnedSectionListView 是继承了ListView ,可以不用管内部具体,在这里只用到普通的ListView 就可以了
。。。
在我们拿到了 视频文件信息 ArrayList 并且传到了 MyImageAdapter 内部前提下
,Adapter内部结构如下:
package com.example.jiuan_item3; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map; import android.annotation.SuppressLint;
import android.app.ActionBar.LayoutParams;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; /**
* // * listview适配器,设置特殊item(为蓝色背景的首字母栏) //
*/
public class MyImageAdapter extends BaseAdapter {
private Context context;
private ArrayList<VideoBean> datas;
public Map<String, Integer> maps;
private MyVideoThumbLoader mVideoThumbLoader; /**
* @param context
* @param datas
* 具有数据提供的构造
*/
public MyImageAdapter(Context context, ArrayList<VideoBean> datas) {
this.context = context;
this.datas = datas;
sortLetter(datas);
mVideoThumbLoader = new MyVideoThumbLoader();// 初始化缩略图载入方法
} /**
* 获取需要顶部悬浮显示的view,这是另外的功能,可不理会
*/
public View getPinnedSectionView(int position) {
ViewGroup view = (ViewGroup) getView(position, null, null);// x
View vAlpha = view.getChildAt(0);
return vAlpha;
} @Override
public int getCount() {
return datas.size();
} @Override
public VideoBean getItem(int position) {
return datas.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) { View view = View.inflate(context, R.layout.alpha_item, null);
final TextView tvAlpha = (TextView) view
.findViewById(R.id.alphaitem_tv_alpha);
TextView tvContent = (TextView) view
.findViewById(R.id.alphaitem_tv_content);
ImageView tvImg = (ImageView) view.findViewById(R.id.imgview); VideoBean myData = getItem(position); tvAlpha.setText(myData.getFileParentVideo());
//实现分组的功能,可不理会
if (maps.get(myData.getFileParentVideo()) == position) {
tvAlpha.setVisibility(View.VISIBLE);
} else {
tvAlpha.setVisibility(View.GONE);
}
tvAlpha.setTag(position);
//重点代码
String path = datas.get(position).getLocationPath();
tvImg.setTag(path);//绑定imageview
mVideoThumbLoader.showThumbByAsynctack(path, tvImg); tvContent.setText(datas.get(position).getVidioName()); return view;
} private void sortLetter(ArrayList<VideoBean> datas) {
// 这是个分组的排序算法,为了让所有的数据统一性
Collections.sort(datas, new Comparator<VideoBean>() {
@Override
public int compare(VideoBean lhs, VideoBean rhs) {
return lhs.getFileParentVideo().compareTo(
rhs.getFileParentVideo());
}
});
maps = new HashMap<String, Integer>();
for (int i = 0; i < datas.size(); i++) {
if (!maps.containsKey(datas.get(i).getFileParentVideo())) {
maps.put(datas.get(i).getFileParentVideo(), i);
}
}
}
}
上面代码中运用到了 MyVideoThumbLoader,这个类,所有贴出这个代码如下:
package com.example.jiuan_item3; import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v4.util.LruCache;
import android.widget.ImageView; public class MyVideoThumbLoader {
private ImageView imgView;
private String path;
//创建cache
private LruCache<String, Bitmap> lruCache; @SuppressLint("NewApi")
public MyVideoThumbLoader(){
int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取最大的运行内存
int maxSize = maxMemory /4;//拿到缓存的内存大小 lruCache = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//这个方法会在每次存入缓存的时候调用
return value.getByteCount();
}
};
} public void addVideoThumbToCache(String path,Bitmap bitmap){
if(getVideoThumbToCache(path) == null){
//当前地址没有缓存时,就添加
lruCache.put(path, bitmap);
}
}
public Bitmap getVideoThumbToCache(String path){ return lruCache.get(path); }
public void showThumbByAsynctack(String path,ImageView imgview){ if(getVideoThumbToCache(path) == null){
//异步加载
new MyBobAsynctack(imgview, path).execute(path);
}else{
imgview.setImageBitmap(getVideoThumbToCache(path));
} } class MyBobAsynctack extends AsyncTask<String, Void, Bitmap> {
private ImageView imgView;
private String path; public MyBobAsynctack(ImageView imageView,String path) {
this.imgView = imageView;
this.path = path;
} @Override
protected Bitmap doInBackground(String... params) {
//这里的创建缩略图方法是调用VideoUtil类的方法,也是通过 android中提供的 ThumbnailUtils.createVideoThumbnail(vidioPath, kind);
Bitmap bitmap = VideoUtil.createVideoThumbnail(params[0], 70, 50, MediaStore.Video.Thumbnails.MICRO_KIND);
//加入缓存中
if(getVideoThumbToCache(params[0]) == null){
addVideoThumbToCache(path, bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(imgView.getTag().equals(path)){//通过 Tag可以绑定 图片地址和 imageView,这是解决Listview加载图片错位的解决办法之一
imgView.setImageBitmap(bitmap);
}
}
}
}
通过上面的 videoThumbLoader类,就可以看出这个机制的核心所在,异步方法实现图片的加载,这样不会阻塞ui线程,然后缓存加载,又可以节省加载时间;然后在 adapter的geiViewf方法里调用设置缩略图;为了节省每次都去创建缩略图的时间,LruCache实现了图片的缓存机制,LruCache其实底层就是一个 HashMap map 类;具体可以百度下LruCache
public MyVideoThumbLoader(){
int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取最大的运行内存
int maxSize = maxMemory /4;
lruCache = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//这个方法会在每次存入缓存的时候调用,必须要实现的方法
return value.getByteCount();
}
};
}
就这样,全部代码写完了;这个视频缩略图的加载和显示都完美的实现了;
不过以上都是核心代码,如果你看的不是很明白可以留言,
我会上传源码
本版为原创,转载请注明来路;要尊重程序员
android 视频的缩略图 缓存机制和 异步加载缩略图的更多相关文章
- Android学习笔记(二)之异步加载图片
最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...
- Android中图片的异步加载
转: 1. 为什么要异步加载图片 下载图片比较费时,先显示文字部分,让加载图片的过程在后台,以提升用户体验 2. SoftReference的作用 栈内存—引用 堆内存—对象 Eg: Object ...
- [Android Pro] 使用CursorLoader异步加载数据 from 3.0
Android 3.0引入了CursorLoader实现异步加载数据,为了避免同步查询数据库时阻塞UI线程的问题.在API 11之前可以通过下载支持库,来使之前的系统支持此功能,下载页面为 http: ...
- 多线程异步加载图片async_pictures
异步加载图片 目标:在表格中异步加载网络图片 目的: 模拟 SDWebImage 基本功能实现 理解 SDWebImage 的底层实现机制 SDWebImage 是非常著名的网络图片处理框架,目前国内 ...
- Android-LoaderManager异步加载数据库数据
LoaderManager异步加载数据库数据,是在(Activity/fragment/其他UI等) 加载大量的本地Database库表数据,由于数据大在加载过程中会导致UI线程阻塞,导致用户体验不好 ...
- wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)
wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...
- Android异步加载图像(含线程池,缓存方法)
研究了android从网络上异步加载图像: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new 一个Han ...
- Android批量图片加载经典系列——采用二级缓存、异步加载网络图片
一.问题描述 Android应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取.再从文件中获取,最后才会访问网络. ...
- android ListView异步加载图片(双缓存)
首先声明,参考博客地址:http://www.iteye.com/topic/685986 对于ListView,相信很多人都很熟悉,因为确实太常见了,所以,做的用户体验更好,就成了我们的追求... ...
随机推荐
- win10蓝屏问题,关于驱动kisSaasUrlRedirectKnl64.sys 的
上周末刚从win7升级到win10:今天出现了两次蓝屏了,都是显示: xxxxxxx 百度知道链接---http://zhidao.baidu.com/question/164141456570387 ...
- php中抓取网页内容的代码
方法一: 使用file_get_contents方法实现 $url = "http://news.sina.com.cn/c/nd/2016-10-23/doc-ifxwztru695114 ...
- asp.net mvc 动态显示不同的部分视图
首先是AJAX请求 //第一次打开 默认s单行文本 $.ajax({ type: "GET", url: "/Admin/Field/ChoiceType4Edit&qu ...
- Android开发:第四日番外——Assets文件夹和RAW文件夹区别
话说上回说到SQLite数据库,其中涉及到把已经设计好的数据库打包到APK中,提到可以放置在Assert文件夹或者RAW文件夹中,那么两者到底有什么区别呢?让我们来探究一下. 一.res/raw和as ...
- ps中如何用抽出功能扣取头发
一些图片中需要扣取人的头发,非常不好扣,本文介绍抽取扣除 打开一个人物图片,用ctrj+j分别复制几个图层,从下往上分别为:背景副本,图层2(用于修改成别的背景),图层1抽头发白色(用于抽头发,强制前 ...
- 手机软件mockup设计工具
软件界面设计工具 UIDesigner v2.5 详见 http://www.downyi.com/downinfo/26770.html
- 【转】mac/linux终端光标的快捷键操作
摘自网络:原标题是类似linux/unix命令行终端的光标及字符控制快捷键的东东. 常用的快捷键: Ctrl + d 删除一个字符,相当于通常的Delete键(命令行若无所有字符,则相当于exit:处 ...
- c#上iOS apns p12文件制作记录
1.在桌面上建一个"apns_p12"文件夹,所有的保存和生成文件都放在这里 2.从钥匙串中生成CertificateSigningRequest.certSigningReque ...
- 使用WebApi时Post和Put的区别
简单的说Post是添加,Put是修改 吃不准的话,尝试用相同参数访问二次接口,结果不同的是Post(会产生多条记录),结果相同的是Put(仅为一条记录),例如:写博客就是Post:更新签名就是Put
- wordpress使用技巧
1.iis6下wordpress去掉index.php 1)安装ISAPIRewritev3.1.0.73 http://bbs.z.admin5.com/forum.php?mod=viewthre ...