安卓缓存那些事情面试,一篇全部搞定

news2024/11/15 19:29:48

安卓缓存那些事情面试,一篇全部搞定

  • 安卓缓存机制
  • LruCache算法
  • 手写Bitmap的三级缓存
    • 一.为什么Bitmap三级缓存?
    • 二.原理
    • 三.代码
  • Bitmap的二次采样和质量压缩
    • 一.为什么二次采样
    • 二.哪二次采样
    • 三.代码:网络请求图片进行尺寸压缩
    • 四.质量压缩
      • 1.方法介绍
      • 2.案例:将一张Bitmap图片采用50%质量压缩到SD卡中
  • RecyclerView四级缓存

安卓缓存机制

在这里插入图片描述
1.网络缓存:服务器缓存数据
2.本地持久化缓存:磁盘缓存,数据库db文件,SP xml文件,ACache文件缓存(https://blog.iprac.cn/blogs/285.html)
3.内存缓存:
4.活动缓存:
其中磁盘缓存和内存缓存都涉及到LruCache算法,下面我们一起来研究LruCache算法

LruCache算法

记住2个关键字:近期最少使用原则/LinkedHashMap

https://blog.csdn.net/zenmela2011/article/details/125191137

手写Bitmap的三级缓存

一.为什么Bitmap三级缓存?

  1. 没有缓存的弊端 :费流量, 加载速度慢
  2. 加入缓存的优点: 省流量,支持离线浏览

二.原理

在这里插入图片描述

思路:

  1. 从内存获取图片, 如果存在, 则显示; 如果不存在, 则从SD卡中获取图片
  2. 从SD卡中获取图片, 如果文件中存在, 显示, 并且添加到内存中; 否则开启网络下载图片
  3. 从网络下载图片, 如果下载成功, 则添加到缓存中, 存入SD卡, 显示图片

三.代码

(1)添加读写SD卡的权限和网络权限

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
 <uses-permission android:name="android.permission.INTERNET"></uses-permission>

(2)操作内存工具类:提供从内存中读写的方法,内存不能持久保存,可能过一会就会被回收掉

 //Lrucache存储工具类
public class LruUtils {
    //TODO 1:实例化LruCache对象
    private LruCache<String,Bitmap> lruCache;
    private long max=Runtime.getRuntime().maxMemory();//获得手机的最大内存
    public LruUtils(){
        lruCache=new LruCache<String,Bitmap>((int)max/8){//给内存大小,一般是最大内存的1/8
            //重写该方法返回每个对象的大小
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount();
            }
        };
    }
    //TODO 2:读图片
    public Bitmap getBitmap(String key){
        return lruCache.get(key);
    }
    //TODO 3:存图片
    public  void setBitmap(String key,Bitmap bitmap){
        lruCache.put(key,bitmap);
    }
}

(3)操作SD卡工具类:提供从SD卡中读写的方法

 //TODO 读图片和写图片
public class SDUtils {
    //TODO 1:存图片:bitmap.compress()
    public static void setBitmap(String name,Bitmap bitmap){
        //获取路径存储图片
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File file1=new File(file,name);
            //存储图片:bitmap对象---->SD卡
            try {
                //参数一 图片的格式 参数二 图片质量 0-100  参数三:输出流
                bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file1));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    //TODO 2:读图片:BitmapFactory.decodeFile()
    public static Bitmap getBitmap(String name){
        //获取路径存储图片
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File file1=new File(file,name);
            //读取图片:SD卡-----Bitmap
            return BitmapFactory.decodeFile(file1.getAbsolutePath());

        }
        return null;
    }
}

(3)网络下载工具类:提供下载图片的方法

 //网络获取工具类
public class NetUtils {
    //TODO 获取网络图片
    public static Bitmap getBitmap(String url) throws ExecutionException, InterruptedException {
         return new MyTask().execute(url).get();//get方法获取执行完毕返回的结果Bitmap对象
    }

    static class MyTask extends AsyncTask<String,String,Bitmap>{
        @Override
        protected Bitmap doInBackground(String... strings) {
            String imageUrl = strings[0];
            HttpURLConnection conn = null;
            try {
                URL url = new URL(imageUrl);
                conn = (HttpURLConnection) url.openConnection(); // 打开连接
                conn.setReadTimeout(5000); // 设置读取超时时间
                conn.setConnectTimeout(5000); // 设置连接超时时间
                conn.setRequestMethod("GET"); // 设置请求方式
                if (conn.getResponseCode() == 200) {
                    InputStream is = conn.getInputStream(); // 获取流数据
                    Bitmap bitmap = BitmapFactory.decodeStream(is); // 将流数据转成Bitmap对象
                    return bitmap;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    conn.disconnect(); // 断开连接
                }
            }
            return null;
        }
    }

}

(4)使用三个工具类完成Bitmap的三级缓存

 /*
一。三级缓存
1.运行内存:LruUtils(创建实例,存,读)
2.文件SD
3.网络请求
* */
public class MainActivity extends AppCompatActivity {
    private ImageView imageView;
    private  LruUtils lruUtils= new LruUtils();//TODO 注意:同一个内存对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView=findViewById(R.id.image);
    }

    public void click(View view) throws ExecutionException, InterruptedException {
        //TODO 1:先从运行内存中读取
        Bitmap bitmap=lruUtils.getBitmap("宋定行");
        if(bitmap!=null){//有图片
            imageView.setImageBitmap(bitmap);
            Toast.makeText(this, "图片来自内存", Toast.LENGTH_SHORT).show();
        }else{
            //TODO 2:若内存没有去SD卡
            bitmap=SDUtils.getBitmap("宋定行.jpg");
            if(bitmap!=null){
                imageView.setImageBitmap(bitmap);
                Toast.makeText(this, "图片从SD卡来de", Toast.LENGTH_SHORT).show();
                //向内存中存储一下
                lruUtils.setBitmap("宋定行",bitmap);
            }else{
                //TODO 3:运行内存和SD卡都没有图片,接下来网络获取
                bitmap=NetUtils.getBitmap("http://upload.cbg.cn/2015/1126/1448506973451.jpg");
                if(bitmap!=null){
                    imageView.setImageBitmap(bitmap);
                    Toast.makeText(this, "图片从网络获取", Toast.LENGTH_SHORT).show();
                    //将图片再放到SD卡和内存中
                    SDUtils.setBitmap("宋定行.jpg",bitmap);
                    lruUtils.setBitmap("宋定行",bitmap);
                }else{
                    Toast.makeText(this, "穷玩意检查下你的网吧", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}

Bitmap的二次采样和质量压缩

一.为什么二次采样

在这里插入图片描述

二.哪二次采样

在这里插入图片描述

三.代码:网络请求图片进行尺寸压缩

第一次:获得缩放比例 ,是2的幂次
第二次:根据缩放比例进行压缩

public class Main5Activity extends AppCompatActivity {
    Button bt;
    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt=findViewById(R.id.bt);
        imageView=findViewById(R.id.iv);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //网络获取一张大图,进行二次采样之后再放到ImageView
                //https://cdn.duitang.com/uploads/item/201211/24/20121124230042_Bfhim.jpeg
                try {
                    Bitmap bitmap = new MyTask().execute("https://cdn.duitang.com/uploads/item/201211/24/20121124230042_Bfhim.jpeg").get();
                    imageView.setImageBitmap(bitmap);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }

            }
        });
    }
    class MyTask extends AsyncTask<String,Object,Bitmap>{

        @Override
        protected Bitmap doInBackground(String... strings) {
            try {
                URL url = new URL(strings[0]);
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                if(urlConnection.getResponseCode()==200){
                    InputStream inputStream = urlConnection.getInputStream();
                    //将inputStream流存储起来
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    byte[] bytes = new byte[1024];
                    int len=0;
                    while((len=inputStream.read(bytes))!=-1){
                        byteArrayOutputStream.write(bytes,0,len);
                    }
                    //桶:网络的图片都放在数组里面了
                    byte[] data = byteArrayOutputStream.toByteArray();
                    //TODO 1:第一次采样:只采边框 计算压缩比例
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds=true;//设置只采边框
                    BitmapFactory.decodeByteArray(data,0,data.length,options);//采样
                    int outWidth = options.outWidth;//获得原图的宽
                    int outHeight = options.outHeight;//获得原图的高
                    //计算缩放比例
                    int size=1;
                    while(outWidth/size>100||outHeight/size>100){
                        size*=2;
                    }
                    //TODO 2:第二次采样:按照比例才像素
                    options.inJustDecodeBounds=false;//设置只采边框为fasle
                    options.inSampleSize=size;//设置缩放比例
                    Bitmap bitmap=BitmapFactory.decodeByteArray(data,0,data.length,options);//采样
                    return  bitmap;
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

}

四.质量压缩

1.方法介绍

Bitmap.compress(CompressFormat format, int quality, OutputStream stream)
参数一:Bitmap被压缩成的图片格式
参数二:压缩的质量控制,范围0~100
参数三:输出流

2.案例:将一张Bitmap图片采用50%质量压缩到SD卡中

//判断SD卡是否挂载
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
		//获得SD卡的跟路径
            File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File file1=new File(file,name);
            //存储图片:bitmap对象---->SD卡
            try {
                //参数一 图片的格式 参数二 图片质量 0-100  参数三:输出流
                bitmap.compress(Bitmap.CompressFormat.JPEG,50,new FileOutputStream(file1));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

RecyclerView四级缓存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/487739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

携手中国电信打造 5G 智慧机场, ALVA Systems 创新 AR 应用闪耀云生态成果展

4 月 26 日&#xff0c;由国家网信办、国家发改委、科技部、工信部、国务院国资委、福建省人民政府共同主办&#xff0c;福州市人民政府等有关单位承办的第六届数字中国建设峰会数字福州暨生态大会在福州举办。 作为数字中国建设主力军之一&#xff0c;中国电信天翼云重磅亮相&…

Shell脚本编程入门--Day1

文章目录 什么是shell&#xff1f;变量环境变量的设置和显示特殊变量特殊的状态变量 什么是shell&#xff1f; 从技术角度&#xff0c;Shell的最简单定义&#xff1a;命令行解释器&#xff08;command Interpreter&#xff09;主要包含&#xff1a; 1, 将使用者的命令翻译给核…

COS 压测指南

COSBench 简介 COSBench 是一款由 Intel 开源&#xff0c;用于对象存储的压测工具。腾讯云对象存储&#xff08;Cloud Object Storage&#xff0c;COS&#xff09;作为兼容 S3 协议的对象存储系统&#xff0c;可使用该工具进行读写性能压测。 系统环境 工具推荐运行在 CentO…

PyCharm 下载安装教程(中文语言包)

文章目录 下载安装简单创建项目中文语言包 Py Charm是由JetBrains打造的一款Python IDE&#xff08;Integrated Development Environment&#xff0c;集成开发环境&#xff09; 下载 点击链接进入官网&#xff1a;https://www.jetbrains.com/pycharm/download/#sectionwindows …

PM864AK01-eA一极用于直流电压电平,地面是用于海底/地下电缆的永久返回路径

​ PM864AK01-eA一极用于直流电压电平&#xff0c;地面是用于海底/地下电缆的永久返回路径 高压直流输电 电力以交流电的形式产生和传输&#xff0c;但对于长距离传输&#xff0c;会产生很大的损耗&#xff0c;或者在两个交流系统无法同步的情况下。所以我们可以用直流输电的方…

【Java EE】-HTTP请求构造以及HTTPS的加密流程

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【JavaEE】 分享: 在满园弥漫的沉静的光芒之前&#xff0c;一个人更容易看到时间&#xff0c;并看到自己的身影。——史铁生《我与地坛》 主要内容&#xff1a;构造http请求&…

大数据Doris(十一):Aggregate 数据模型

文章目录 Aggregate 数据模型 一、导入数据聚合 二、保留明细数据

16 opencv 图像开和闭运算

文章目录 形态学处理操作函数核操作 综合案例 形态学处理 处理类型操作作用开运算先腐蚀再膨胀可在纤细点出分离物体。有助于消除噪音闭运算先膨胀后腐蚀用于排除前景对象中的小孔或对象上的小黑点形态学梯度膨胀图与腐蚀图之差用于保留目标物体的边缘轮廓顶帽原图与开运算图之…

AIgo C++ 面向ai算法的c++

https://github.com/shouxieai/algorithm-cpp http://aipj.aijdjy.com/course/13/task/266/show# https://www.yuque.com/books/share/0729cafa-4751-40e5-9f5d-bb617c0e9708?# 《C》 &#x1f4bb; AI算法视角下的c 视频问手写ai vx: shouxie_ai [共11节课&#xff0c;每节课…

企业微信第三方应用发邮件流程及java代码

具体思路&#xff1a; 1、申请企业微信。 2、在企业微信创建一个邮箱。 3、自建第三方应用。 4、从第三方应用&#xff0c;获取“Secret”值。 5、在第三方应用中&#xff0c;建立企业可信IP。 6、获取企业corpid。 7、写java代码&#xff0c;获取access_token。 参考&a…

华为开源自研AI框架昇思MindSpore应用案例:ResNet50迁移学习

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 AI融合计算的蓬勃发展&#xff0c;对框架能力提出了新的需求和挑战。问题场景和模型设计逐渐复杂化&#xff0c;使得业务数据的维度和计算逻辑的嵌套深度也相应增长。结合向量化优化手段可以有效优化性能瓶…

Delving into Localization Errors for Monocular 3D Object Detection 论文学习

论文地址&#xff1a;Delving into Localization Errors for Monocular 3D Object Detection Github地址&#xff1a;Delving into Localization Errors for Monocular 3D Object Detection 1. 解决了什么问题&#xff1f; 从单目图像准确地估计 3D 框是自动驾驶领域的重要功…

图像去模糊中的均值滤波、高斯滤波、双边滤波简单介绍及代码演示

文章目录 图像去模糊中的均值滤波、高斯滤波和双边滤波简单介绍均值滤波高斯滤波双边滤波总结 图像去模糊中的均值滤波、高斯滤波和双边滤波简单介绍 图像模糊是指图像中的细节和边缘被平滑和模糊化&#xff0c;通常是由于图像采集设备或者图像传输过程中的噪声和抖动引起的。…

SQL 执行顺序

数据的关联过程 from&join&where group by having&where select order by limit 这是一条标准的查询语句: 这是我们实际上SQL执行顺序&#xff1a; 我们先执行from,join来确定表之间的连接关系&#xff0c;得到初步的数据 where对数据进行普通的初步的筛选 …

低代码开发重要工具:jvs列表页中如何实现左树右表的配置

左树右表是一种数据查询展示方式&#xff0c;通常用于处理带有层级关系的查询条件的数据展示。它的基本思想是将一个大表分成左树和右表&#xff0c;左树是一个树形结构&#xff0c;右表是一个扁平的表。通过在左树上建立索引&#xff0c;可以大大提高查询效率。 左树右表的实…

C/C++每日一练(20230504)

目录 1. 将数据流变为多个不相交区间 &#x1f31f;&#x1f31f;&#x1f31f; 2. 冒泡法排序大小 &#x1f31f; 3. Pow(x, n) &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专…

使用机器人为无线传感器网络提供服务(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 无线传感器网络是一种无线网络&#xff0c;包括大量循环的、自定向的、微小的、低功耗的设备&#xff0c;称为传感器节点&…

MySQL存储引擎对比总结

文章目录 一、存储引擎是什么二、存储引擎有哪些三、常用存储引擎介绍1、InnoDB2、MyISAM3、MEMORY4、MRG_MYISAM &#xff08;MERGE&#xff09;5、ARCHIVE6、BLACKHOLE7、FEDERATED8、CSV9、PERFORMANCE_SCHEMA10、NDB 一、存储引擎是什么 存储引擎是数据库的核心&#xff0…

微信小程序实现订阅消息功能(Node服务器篇)

在上一篇内容当中在微信小程序中实现订阅消息功能&#xff0c;都在客户端(小程序)中来实现的&#xff0c;在客户端中模拟了服务器端来进行发送订阅消息的功能&#xff0c;那么本篇就将上一篇内容中仅在客户端中实现发送订阅消息功能进行一个分离&#xff0c;使用 Node.js 搭载后…

吧佬联手抵制奸商,百元级游戏电脑横出江湖

最近小忆闲得在电商平台搜索了下关键词「游戏主机」&#xff0c;不出意外销量榜前列清一色全是「i9 级高端游戏主机」。 这些主机不论配置单介绍还是十万百万级销量宣传标语&#xff0c;都给人一种血赚不亏的「豪华」感。 咱就说时代在变&#xff0c;唯一不变的是奸商们的套路与…