AndroidVideoCache实现预缓存
一、概述
案例:实现一个视频预缓存的需求
原理:
1.本地有缓存就优先播放缓存,本地没有缓存就从服务端拉取数据存入缓存,然后再读取缓存播放
2.要实现1中描述的功能,a.首先要再App中新建一个代理服务 b.客户端请求代理服务 c.代理服务收到客户端请求,开启一个线程A发起请求网络服务器,d.将线程A中获取到的数据写入本地缓存 e.客户端从本地缓存中读取数据并播放。
使用到的技术及框架:
1.本例是在上一篇文章中使用到的AndroidVideoCache框架的基础上进行改造的。
2.主要是加入了预缓存的功能PreLoadManager
源代码下载:
二、代码示例
1.新建一个单例类PreLoadManager
1 | PreloadManager |
2.在PreLoadManager类中定一个Map用来存储所有的任务,其中key为url ,value为具体的任务
1 2 3 4 | /** * 保存正在预加载的{@link PreloadTask} */ private LinkedHashMap<String, PreloadTask> mPreloadTasks = new LinkedHashMap<>(); |
3.添加一个任务到任务池子中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * 开始预加载 * * @param rawUrl 原始视频地址 */ public void addPreloadTask(String rawUrl, int position) { if (isPreloaded(rawUrl)) return ; PreloadTask task = new PreloadTask(); task.mRawUrl = rawUrl; task.mPosition = position; task.mCacheServer = mHttpProxyCacheServer; Log.i(TAG, "addPreloadTask: " + position); mPreloadTasks.put(rawUrl, task); if (mIsStartPreload) { //开始预加载 // Log.i(TAG,"开始预加载: " + position); task.executeOn(mExecutorService); } } |
通过task.executeOn(mExecutorService)方法就立即开始执行任务,其执行的核心代码如下所示:
/** * 开始预加载 */ private void start() { Log.i(TAG,"开始预加载:" + mPosition); HttpURLConnection connection = null; try { //获取HttpProxyCacheServer的代理地址 String proxyUrl = mCacheServer.getProxyUrl(mRawUrl); Log.e("预加载的路径:",proxyUrl); URL url = new URL(proxyUrl); connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(10000); connection.setReadTimeout(10000); InputStream in = new BufferedInputStream(connection.getInputStream()); int length; int read = -1; byte[] bytes = new byte[8 * 1024]; while ((length = in.read(bytes)) != -1) { read += length; //预加载完成或者取消预加载 if (mIsCanceled || read >= PreloadManager.PRELOAD_LENGTH) { Log.i(TAG,"结束预加载:" + mPosition); break; } } if (read == -1) { //这种情况一般是预加载出错了,删掉缓存 Log.i(TAG,"预加载失败:" + mPosition); File cacheFile = mCacheServer.getCacheFile(mRawUrl); if (cacheFile.exists()) { cacheFile.delete(); } } } catch (Exception e) { e.printStackTrace(); Log.i(TAG,"异常结束预加载:" + mPosition+"|"+e.getMessage()+"\n"+mCacheServer.getProxyUrl(mRawUrl)); } finally { if (connection != null) { connection.disconnect(); } } }
其本质上就是模拟了一个客户端发起了一个网络请求,当这个网络请求获取到的数据包的到校>=512kb的时候立马终止线程。客户端线程终止后最终会调用HttpProxyCacheServerClients的finishProcessRequest()方法,同时停止真正下载数据的线程。
4.取消任务
/** * 停止所有的预缓存任务 */ public void stopAllPreloadTask() { Iterator<Map.Entry<String, PreloadTask>> iterator = mPreloadTasks.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, PreloadTask> next = iterator.next(); PreloadTask task = next.getValue(); task.cancel(); } }
5.设置预缓存的大小
1 2 3 4 | /** * 预加载的大小,每个视频预加载512KB,这个参数可根据实际情况调整 */ public static final int PRELOAD_LENGTH = 1024 * 1024 * 1; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2013-12-08 使用Android绘图技术绘制一个椭圆形,然后通过触摸事件让该椭圆形跟着手指移动
2013-12-08 Android解决自定义View获取不到焦点的情况