牙叔教程 简单易懂
这种setImageBitmap必须主动回收图片,
bitmap已经赋值给了你定义的变量, 既然你给图片添加了新的引用,
那么这张图片就归你管, 系统就不管了
"ui"; ui.layout( <vertical> <img id="img"></img> </vertical> ); let img = images.read(imgPath); let bitmap = img.bitmap; ui.img.setImageBitmap(bitmap); events.on("exit", function () { img.recycle(); });
这种就不用自己主动回收图片,
因为你没有对图片进行引用, 引用是系统自己搞的, 系统可以处理
"ui"; ui.layout( <vertical> <img id="img" src="file://{{imgPath}}"></img> </vertical> );
这种也不用自己主动回收图片, 原因同上
ui.layout( <vertical> <img id="img"></img> </vertical> ); ui.img.attr("src", "file://" + imgPath);
下面来看看RecyclerView中使用图片的情况
这是使用 img.attr("src", "file://" + data.imgPath);
不需要主动回收, 但是滑动rv的时候, 有点卡,
因为每次加载数据, 都去读取一遍图片
ui.layout( <vertical> <text text="牙叔教程 简单易懂" textSize="28sp" textColor="#fbfbfe" bg="#00afff" w="*" gravity="center"></text> <androidx.recyclerview.widget.RecyclerView id="recyclerView"></androidx.recyclerview.widget.RecyclerView> </vertical> ); let imgPath = "/storage/emulated/0/脚本/ui界面图片回收/" + "road.jpg"; let dataList = []; var len = 33; for (var i = 0; i < len; i++) { dataList.push({ imgPath: imgPath, }); } let recyclerView = ui.recyclerView; let layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); let recycleAdapter = createRecyclerViewAdapter(dataList); recyclerView.setAdapter(recycleAdapter); /* ---------------------------自定义函数----------------------------------------------- */ function createRecyclerViewAdapter(dataList) { let boxXml = ( <horizontal id="horizontalParent"> <text id="num"></text> <img id="img"></img> </horizontal> ); return RecyclerView.Adapter({ onCreateViewHolder: function (parent, viewType) { log("onCreateViewHolder"); // 视图创建 let view; let holder; view = ui.inflate(boxXml, parent, false); holder = JavaAdapter(RecyclerView.ViewHolder, {}, view); return holder; }, onBindViewHolder: function (holder, position) { // log("onBindViewHolder"); // 数据绑定 let data = dataList[position]; holder.itemView.num.setText(position + ""); holder.itemView.img.attr("src", "file://" + data.imgPath); }, getItemCount: function () { return dataList.length; }, }); }
我们把onBindViewHolder改写一下, 如果已经加载过一次图片, 就不用执行 img.attr("src"这个命令了,
这属于最简单的缓存吧
onBindViewHolder: function (holder, position) { let data = dataList[position]; holder.itemView.num.setText(position + ""); if ("file://" + imgPath !== holder.itemView.img.attr("src")) { log("需要读取图片"); holder.itemView.img.attr("src", "file://" + data.imgPath); } else { log("不需要读取图片"); } },
修改之后, 除了一开始加载的前几张图片有点卡之外, 其他的一点都不卡, 丝滑的很,
那么问题还是有的, 如何让前几张图片, 滑动的时候, 也不要卡呢?
我们提前读取图片试试, 也就是用setImageBitmap
let imgPath = "/storage/emulated/0/脚本/ui界面图片回收/" + "road.jpg"; let dataList = []; var len = 33; let img = images.read(imgPath); let bitmap = img.bitmap; for (var i = 0; i < len; i++) { dataList.push({ imgPath: imgPath, img: img, bitmap: bitmap, }); } events.on("exit", function () { img.recycle(); }); ui.layout( <vertical> <text text="牙叔教程 简单易懂" textSize="28sp" textColor="#fbfbfe" bg="#00afff" w="*" gravity="center"></text> <androidx.recyclerview.widget.RecyclerView id="recyclerView"></androidx.recyclerview.widget.RecyclerView> </vertical> ); let recyclerView = ui.recyclerView; let layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); let recycleAdapter = createRecyclerViewAdapter(dataList); recyclerView.setAdapter(recycleAdapter); /* ---------------------------自定义函数----------------------------------------------- */ function createRecyclerViewAdapter(dataList) { let boxXml = ( <horizontal id="horizontalParent"> <text id="num"></text> <img id="img"></img> </horizontal> ); return RecyclerView.Adapter({ onCreateViewHolder: function (parent, viewType) { log("onCreateViewHolder"); // 视图创建 let view; let holder; view = ui.inflate(boxXml, parent, false); holder = JavaAdapter(RecyclerView.ViewHolder, {}, view); return holder; }, onBindViewHolder: function (holder, position) { let data = dataList[position]; holder.itemView.num.setText(position + ""); holder.itemView.img.setImageBitmap(data.bitmap); }, getItemCount: function () { return dataList.length; }, }); }
试了一下bitmap, 真的很丝滑呢, 起码小米11pro是丝滑的,
我们的dataList有33条数据, 每条数据使用的都是同一张图片的bitmap,
我们来试试33张不同的图片, 看会不会卡顿
修改dataList即可, 注意, bitmap是需要自己主动回收的
let img = images.read(imgPath); for (var i = 0; i < len; i++) { let newImg = img.clone(); let bitmap = newImg.bitmap; dataList.push({ imgPath: imgPath, img: newImg, bitmap: bitmap, }); } events.on("exit", function () { img.recycle(); dataList.map(function (item) { item.img.recycle(); }); });
基本和使用同一张图片的bitmap效果一样, 感觉不到卡顿.
这就表明, 读取图片是最消耗资源的, 我们尽量少的去读取图片, 尽量早的读取图片,
尤其要在ui中, 减少此类耗时操作, 不然, 卡顿是避免不了的.
现在加载33张图片, 还算可以吧.
如果我们加载3333张图片呢? 我觉得光是提前读取图片就会非常卡了, 非常耗时,
说不定就OOM了(Out Of Memory),
所以在数量级上去之后, 我们是不会提前读取全部图片的,
我们只会读取一小部分图片, 应该叫预加载吧,
手机是支撑不了同一时刻, 加载那么多图片数据的, 一会就卡爆了,
那么我们设定一个阈值, 只在同一时刻保存阈值以内数量的图片数据,
如果有新的图片需要显示, 那么就删掉以前的旧图片, 这个叫
LruCache(Least Recently Used Cache) 全称最近最少使用算法,其主要思想是使用SoftReference(或者WeakReference),因为我们的缓存容量是有限的,它会面临一个问题:当有新的内容需要加入我们的缓存,但我们的缓存空闲的空间不足以放进新的内容时,我们就需要舍弃原有的部分内容从而腾出空间用来放新的内容。
当然了, 写脚本估计用不到几张图片, 这个LurCache了解即可.
环境
手机: Mi 11 Pro
Android版本: 11
Autojs版本: 9.0.11
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问
--- 牙叔教程
声明
部分内容来自网络
本教程仅用于学习, 禁止用于其他用途