关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android 视频缩略图的缓存机制和异步加载

    Android 视频缩略图的缓存机制和异步加载

    2015-07-27 00:00:00 出处:jcodecraeer
    分享

    在这次的工作开发项目中,涉及到一个视频缩略图的视频列表;这个在大家看来,制作视频缩略图就是两行代码就搞定的事。确实是这样的,百度一下,每个 帖子都知道制作视频缩略图的方法,在这里确实也是一样的,但是我要实现的是让缩略图 在Listview上显示,而且不会出现卡顿,其实也不是特别难,确实很实用;

    主要的实现机制就是 异步加载 和 缓存机制 在加上一个绑定TAG机制;接下来就开始去实现吧

    先上我的是 结构图:

    android 视频的缩略图 缓存机制和 异步加载缩略图

    这个包结构的 自定义 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;//拿到缓存的内存大小 35         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();
                }
            };
        }

    就这样,全部代码写完了;这个视频缩略图的加载和显示都完美的实现了。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。