图片之复习

 二. 图片相关?

五.图片常见的问题

1.图片优化,以及图片加载框架的使用,如Picasso、 Fresco、Glide等?
1)尽量使用小的图片,对图片进行压缩,bitmapfactory.options图片配置类,insimplesize进行缩放,设置图片的编码方式;对图片使用软引用,内存不够时即时释图片内存;对图片的复用,三级缓存的使用;
即时回收不再使用的bitmap对象;
2)Picasso,不支持gif,缓存的是Argb8888的原图,占用内存较大,图片的框架使用了OkHttp缓存机制,使用Http协议缓存,也是异步加载.
3)Fresco,框架是FaceBook公司推出的,适合批量加载图片,底层是通过三级缓存(2级内存,1级磁盘)
加载成功后自动替换成目标图片
4)glide,Google公司14年推出来的,可以加载GIF图,也可以根据指定图片清晰度,底层的原理:为Bitmap维护一个对象池,对象池的目的是通过减少对象的分配,以重用来提高性能.对象池也可以帮助提高滚动的性能。API简洁易调用

2. 缓存
内存缓存(LruCache)、磁盘缓存(DiskLruCache)。
当首次从网络上或者USB读取图片,会对图片进行相应的压缩处理。在处理过后不加入缓存,下一次请求图片还是直接从网络上或者USB中直接读取,不仅消耗了用户的流量还重复对图片进行压缩处理,占用多余内存的同时加载图片也很缓慢。

目前策略是内存缓存和存储设备缓存。当加载一张图片时,首先会从内存中去读取,如果没有就接着在存储设备中读,最后才直接从网络或者USB中读取。

三级缓存:  内存缓存;本地缓存;网络缓存;
当我们第一次打开应用获取图片或其它资源时,首先到网络去下载,然后依次存入内存缓存,磁盘缓存,
当我们再一次需要用到刚才下载的这张图片时,就不需要再重复的到网络上去下载,直接可以从内存缓存和磁盘缓存中找,由于内存缓存速度较快,我们优先到内存缓存中寻找该图片,如果找到则运用,
如果没有找到(内存缓存大小有限),那么我们再到磁盘缓存中去找。
只要我们合理的去协调这三层缓存运用,便可以提升应用性能,给用户更好的体验
三级缓存指的是:内存缓存、本地缓存、网络缓存。其各自的特点是内存缓存速度快, 优先读取,本地缓存速度其次, 内存没有该资源信息就去读取本地内存,网络缓存速度较慢(比较对象是内存缓存和本地缓存),假设本地内存也没有,才请求网络获取。

2.1 LruCache:
LRU是用于实现内存缓存的一种常见算法,LRU也叫做最近最少使用算法,通俗来讲就是当缓存满了的时候,就会优先的去淘汰最近最少使用的缓存对象。

LruCache原理:
LruCache是个泛型类,内部采用LinkedHashMap来实现缓存机制,它提供get方法和put方法来获取缓存和添加缓存,其最重要的方法trimToSize是用来移除最少使用的缓存和使用最久的缓存,并添加最新的缓存到队列中。

private LruCache<Integer,Bitmap> mCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.初始化LruCache.
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mCache = new LruCache<Integer,Bitmap>(cacheSize){
@Override
protected int sizeOf(Integer key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}}; }
//2.从Cache中获取数据
public Bitmap getDataFromCache(int key) {
if (mCache.size() != 0) {
return mCache.get(key);
}
return null;
}
//3.将数据存储到Cache中
public void putDataToCache(int key, Bitmap bitmap) {
if (getDataFromCache(key) == null) {
    mCache.put(key,bitmap);
}}

2.2 DiskLruCache:
磁盘缓存所使用的算法为DiskLruCache,它的使用比内存缓存要复杂一点,但是还是离不开上面的3步,初始化,查找和添加。同样的,

3. 如何加载高清图?
 要求既不能压缩图片,又不能发生oom怎么办,这种情况要加载图片的一部分区域来显示,通过BitmapRegionDecoder这个类,可以加载图片的一部分区域。

4.如何绕过dalvikvm heap size的限制 ?
• 建立子进程,内存分配按进程来。再使用进程通信,就能够把一些对象分配到新进程的heap上了,从而达到一个应用程序使用更多内存的目的,固然,建立子进程会增长系统开销,并且并非全部应用程序都适合这样作,视需求而定。
建立子进程的方法:使用android:process标签
• 按不一样的系统版本,使用 jni 在native heap上申请空间

5. 加载帧动画怎样避免OOM?
原理:
帧动画是按照一定顺序播放一系列图片,从而产生动画。和动漫原理是一样的,本质上是对图片快速的翻页产生动的效果。系统从xml中读取到图片id列表后就去硬盘中找这些图片资源,将图片全部读出来后按顺序设置给ImageView,利用视觉暂留效果实现了动画。
优化方案:
一次拿出这么多图片,而系统都是以Bitmap位图形式读取的;而动画的播放是按顺序来的,大量Bitmap排好队等待播放然后释放,既然这么多Bitmap,一次却只能展示一个,纯属浪费资源,那么可以采取逐帧解析,及时回收。

四. Bitmap优化
展示图片信息,图片最终对应Bitmap对象。而对于APP端来说Bitmap又是一个比较麻烦的问题,主要表现在Bitmap是非常占用内存对象,处理不当将导致APP运行卡顿甚至出现OOM。

1. 不同系统版本的像素数据的内存分配:

Android为每一个进程设置Dalvik Heap Size阈值,这个阈值在不一样设备上会由于RAM大小不一样而各有差别。若是APP想要分配的内存超过这个阈值,就会发生OOM。
Android 5.x之前,Bitmap分配在Native heap中,而在5.x-7.1,Bitmap分配在Dalvik或ART的Java heap中,Android 8.x之后,Bitmap分配在Native heap中。
系统native heap的增加并不受dalvik vm heapsize的限制,只要RAM有剩余空间,程序员能够一直在native heap上申请空间,固然若是 RAM快耗尽,memory killer会杀进程释放RAM。使用一些软件时,有时候会闪退,多是软件在native层申请了比较多的内存致使的。
好比,UC web在浏览内容比较多的网页时闪退,缘由就是其native heap增加到比较大的值,占用了大量的RAM被memory killer杀掉了。

2. Bitmap内存计算:
1).从本地加载或从网络加载用公式计算:图片的长度 * 图片的宽度 * 一个像素点占用的字节数
2).从资源文件夹加载:
    Bitmap内存占用 ≈ 像素数据总大小 = 图片宽 × 图片高× (当前设备密度dpi/图片所在文件夹对应的密度dpi)^2 × 每个像素的字节大小
11)、同一张图片放在不同的资源目录下,其分辨率会有变化。


12)、Bitmap的分辨率越高,其解析后的宽高越小,甚至小于原有的图片(及缩放),从而内存也相应的减少。


13)、图片不放置任何资源目录时,其使用默认分辨率mdpi:160。
    14)、资源目录分辨率和屏幕分辨率一致时,图片尺寸不会缩放。

3、recycle

  • 在安卓3.0以前Bitmap是存放在堆中的,我们只要回收堆内存即可;
  • 在安卓3.0以后Bitmap是存放在内存中的,我们需要回收native层和Java层的内存;
  • 官方建议我们3.0以后使用recycle方法进行回收,该方法也可以不主动调用,因为垃圾回收器会自动收集不可用的Bitmap对象进行回收;
  • recycle方法会判断Bitmap在不可用的情况下,将发送指令到垃圾回收器,让其回收native层和Java层的内存,则Bitmap进入dead状态;
  • recycle方法是不可逆的,如果再次调用getPixels()等方法,则获取不到想要的结果;

3. bitmap优化思路?

3.1 可通过改变图片格式,来改变每个像素占用字节数,从而改变占用的内存。


注:由于ARGB_4444的画质惨不忍睹,一般如对图片没有透明度要求话,可改成RGB_565,相比ARGB_8888节省一半内存开销。
编码: android系统提供了四种编码格式。

其中,A代表透明度,R代表红色,G代表绿色,B代表蓝色。




ARGB_8888 表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节。

ARGB_4444 表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节。


RGB_565 表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节。


ALPHA_8 表示8位Alpha位图,即A=8, 一个像素点占用1个字节,它没有颜色,只有透明度。

3.2 采样率压缩 
bitmap占用内存是以bitmap的宽高和每个像素占用的字节数决定的,按公式可以缩减bitmap的宽高来达到压缩图片占用内存的目的。

BitmapFactory.Options options = new BitmapFactory.Options();
//不获取图片,不加载到内存中,只返回图片属性
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, options);
int outHeight = options.outHeight;
int outWidth = options.outWidth;
Log.d("mmm", "图片宽=" + outWidth + "图片高=" + outHeight);
//计算采样率
int i = utils.computeSampleSize(options, -1, 1000 * 1000);
//设置采样率,不能小于1 假如是2 则宽为之前的1/2,高为之前的1/2,一共缩小1/4 一次类推
options.inSampleSize = i;
Log.d("mmm", "采样率为=" + i);
//图片格式压缩
//options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
float bitmapsize = getBitmapsize(bitmap);
Log.d("mmm","压缩后:图片占内存大小" + bitmapsize + "MB / 宽度=" + bitmap.getWidth() + "高度=" + bitmap.getHeight());

三. Android中图片的压缩方法

Bitmap

  1. Android中图片是以Bitmap(位图)形式存在,位图常见的文件格式有:.bmp .jpg .png .gif 。
  2. Bitmap的大小计算 = 图片的长度*图片的宽度单位像素所占用的字节数。
  3. Bitmap的优缺点

  优点:色彩变化丰富,可以改变任何形状的区域色彩显示效果。
  缺点:放大和缩小都会引起像素的增加和缩小,这样会使图片出现失真或者锯齿形。另一个缺点是像素越高数据量越大占用的内存越大。

常用压缩方法( 1.质量压缩 2.采样率压缩  3. 缩放法压缩)

1) 质量压缩
    质量压缩是改变图片的位深和透明度的,是不会改变图片的宽高(像素)。 质量压缩(降低图片的质量,不会减少图片的像素,没有改变像素大小,所以不会减少占据的内存大小)。

    png是无损压缩的,所以质量压缩对png是不起作用的。

    private void qualityCompress(Bitmap.CompressFormat format, int quality, String type) {
        try {
            File file = new File(Environment.getExternalStorageDirectory(), "test_" + quality + format + "_" + type + ".jpg");
            //得到一个文件输入流
            mFileOutputStream = new FileOutputStream(file);
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pic);
            // 图片的格式  quality是压缩完之后保存图片设置的质量参数  png是无损压缩,quality参数对png无效
            bitmap.compress(format, quality, mFileOutputStream);
        } catch (FileNotFoundException exception) {
            exception.printStackTrace();
        } finally {
            if (mFileOutputStream != null) {
                try {
                    mFileOutputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

2) 采样率压缩( 降低图片的像素。数值越高,图片像素越低。)
  // 尺寸压缩中的采样率压缩(改变了像素,减少了图片占用的内存,同样照片的清晰度也降低了。)
  // inSampleSize =2 内存将减少1/4 内存大小 = 图片宽/inSampleSize * 图片高/inSampleSize*单位像素占用的字节大小

    private void loadImage() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        //设置为true 并会将图片加载到内存中,但是可以获取到图片的宽和高 通过options
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.ic_pic, options);
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        Log.d(TAG, "loadImage: width = " + outWidth);
        Log.d(TAG, "loadImage: height = " + outHeight);
        //这个地方根据获取到大小和想要显示的大小做缩放
        options.inSampleSize = calculateInSampleSize(options, 200, 200);
        Log.d(TAG, "loadImage: inSampleSize = " + options.inSampleSize);
        //设置为false 这回再去解码图片可以将其读取到内存中了。
        options.inJustDecodeBounds = false;
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pic, options);
        File file = new File(Environment.getExternalStorageDirectory(), "text_" + "just_100_no_inSampleSize.jpg");
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();}
            }
        }
     // mImageView.setImageBitmap(mBitmap);
    }

即:如果inJustDecoedBounds设置为true的话,解码bitmap时可以只返回其高、宽和Mime类型,而不必为其申请内存,从而节省了内存空间。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

  // 计算图片的缩放比例
    private int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
        int height = options.outHeight;
        int width = options.outWidth;
        //缩放的比例
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            int halfHeight = height / 2;
            int halfWidth = width / 2;
            while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

3) 尺寸压缩(缩放法压缩)

1. 减小图片的像素,生成的图片file的大小也变小了。
    // 尺寸压缩中的按缩放比压缩。这里的缩放比是事先定义好的和采样率相比,采样率是根据给定的预期大小去计算缩放比

    private void compressBitmapToFile(Bitmap mBitmap, File mFile) {
        //设置压缩倍数
        int ratio = 2;
        //压缩Bitmap到对应的尺寸 压缩格式ARGB_8888 4字节 一个像素需要4个字节来存储
        Bitmap resultBitmap = Bitmap.createBitmap(mBitmap.getWidth() / ratio, mBitmap.getHeight() / ratio, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(resultBitmap);
        Rect rect = new Rect(0, 0, mBitmap.getWidth() / ratio, mBitmap.getHeight() / ratio);
        canvas.drawBitmap(mBitmap, null, rect, null);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        File file = new File(Environment.getExternalStorageDirectory(), "test_compress_100.jpg");
        resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
        try {
            mFileOutputStream1 = new FileOutputStream(file);
            mFileOutputStream1.write(byteArrayOutputStream.toByteArray());
            mFileOutputStream1.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (mFileOutputStream1 != null) {
                try {
                    mFileOutputStream1.close();
                }}
        }
    } 

2.  延伸:一个Bitmap到底占用多大内存?系统给每个应用程序分配多大内存?
1) Bitmap占用的内存为:像素总数 * 每个像素占用的内存。在Android中,Bitmap有四种像素类型:ARGB_8888、ARGB_4444、ARGB_565、ALPHA_8,

       他们每个像素占用的字节数分别为4、2、2、1。因此 一个2000*1000的ARGB_8888类型的Bitmap占用的内存为20001000*4=8000000B=8MB。
2) Android根据设备屏幕尺寸和dpi的不同,给系统分配的单应用程序内存大小也不同,如下表(表格取自Android 4.4 Compatibility Definition Document (CD

二. Bitmap面试题

4、NDK压缩

  Android进阶——图片优化之质量压缩、尺寸压缩、采样率压缩、LibJpeg压缩

  webp压缩

 Android Webp 完全解析 快来缩小apk的大小吧-鸿洋的博客

3、采样率压缩(缩略图)
public static Bitmap thumbnail(String path,int maxWidth, int maxHeight) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(path, options);
    options.inJustDecodeBounds = false;
    int sampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
    options.inSampleSize = sampleSize;
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    options.inPurgeable = true;
    options.inInputShareable = true;
    if (bitmap != null && !bitmap.isRecycled()) {
        bitmap.recycle();
    }
    bitmap = BitmapFactory.decodeFile(path, options);
    return bitmap;  }
4、质量压缩
public static String save(Bitmap bitmap,Bitmap.CompressFormat format, int quality, File destFile) {
    try {
        FileOutputStream out = new FileOutputStream(destFile);
        if (bitmap.compress(format, quality, out)) {
            out.flush();
            out.close();
        }
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        return destFile.getAbsolutePath();
    }return null;
} 
5、尺寸压缩
public static void reSize(Bitmap bmp,File file,int ratio){
    Bitmap result = Bitmap.createBitmap(bmp.getWidth()/ratio, bmp.getHeight()/ratio,Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(result);
    RectF rect = new RectF(0, 0, bmp.getWidth()/ratio, bmp.getHeight()/ratio);
    canvas.drawBitmap(bmp, null, rect , null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    result.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
    }
}
// 计算采样率
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
} 
// 保存到SD卡
public static String save(Bitmap bitmap,Bitmap.CompressFormat format, int quality, Context context) {
    if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        return null;
    }
    File dir = new File(Environment.getExternalStorageDirectory()+ "/" + context.getPackageName() + "/save/");
    if (!dir.exists()) {
        dir.mkdirs();
    }
    File destFile = new File(dir, UUID.randomUUID().toString());
    return save(bitmap, format, quality, destFile);
} 

1、Bitmap 使用时注意什么?

1、要选择合适的图片规格(bitmap类型):

ALPHA_8   每个像素占用1byte内存        
ARGB_4444 每个像素占用2byte内存       
ARGB_8888 每个像素占用4byte内存(默认)      
RGB_565 每个像素占用2byte内存

2、降低采样率。

BitmapFactory.Options 参数inSampleSize的使用,先把options.inJustDecodeBounds设为true,只是去读取图片的大小。 

在拿到图片的大小之后和要显示的大小做比较通过calculateInSampleSize()函数计算inSampleSize的具体值。得到值之后,options.inJustDecodeBounds设为false读图片资源。

3、复用内存。即通过软引用(内存不够的时候才会回收掉),复用内存块,不需要再重新给这个bitmap申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率。

4、使用recycle()方法及时回收内存。

5、压缩图片。

2、bitmap recycler 相关

在Android中,Bitmap的存储分为两部分,一部分是Bitmap的数据,一部分是Bitmap的引用。

在Android2.3时代,Bitmap的引用是放在堆中的,而Bitmap的数据部分是放在栈中的,需要用户调用recycle方法手动进行内存回收。

而在Android2.3之后,整个Bitmap包括数据和引用都放在了堆中,这样整个Bitmap的回收就全部交给GC了,这个recycle方法就再也不需要使用了。

bitmap recycler引发的问题:

当图像的旋转角度小余两个像素点之间的夹角时,图像即使旋转也无法显示。

因此,系统完全可以认为图像没有发生变化。这时系统就直接引用同一个对象来进行操作,避免内存浪费。

3、Oom 是否可以try catch ?

只有在一种情况下,这样做是可行的:

在try语句中声明了很大的对象,导致OOM,并且可以确认OOM是由try语句中的对象声明导致的,那么在catch语句中,可以释放掉这些对象,解决OOM的问题,继续执行剩余语句。

但是这通常不是合适的做法。

Java中管理内存除了显式地catch OOM之外还有更多有效方法:比如SoftReference, WeakReference, 硬盘缓存等。 在JVM用光内存之前,会多次触发GC,这些GC会降低程序运行的效率。

如果OOM的原因不是try语句中的对象(比如内存泄漏),那么在catch语句中会继续抛出OOM。

4、如何计算一个Bitmap占用内存的大小,怎么保证加载Bitmap不产生内存溢出?

Bitamp 占用内存大小 = 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存

注:这里inDensity表示目标图片的dpi(放在哪个资源文件夹下),inTargetDensity表示目标屏幕的dpi,所以你可以发现inDensity和inTargetDensity会对Bitmap的宽高进行拉伸,进而改变Bitmap占用内存的大小。 

在Bitmap里有两个获取内存占用大小的方法。

getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。

getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,代替了 getByteCount() 方法。

在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount 返回的结果是一样的。 

在通过复用Bitmap来解码图片时,那么getByteCount() 表示新解码图片占用内存的大小,getAllocationByteCount() 表示被复用Bitmap真实占用的内存大小(即 mBuffer 的长度)。

为了保证在加载Bitmap的时不产生内存溢出,可以使用BitmapFactory进行图片压缩,主要有以下几个参数:

BitmapFactory.Options.inPreferredConfig:将ARGB_8888改为RGB_565,改变编码方式,节约内存;

BitmapFactory.Options.inSampleSize:缩放比例,可以参考Luban那个库,根据图片宽高计算出合适的缩放比例;

BitmapFactory.Options.inPurgeable:让系统可以内存不足时回收内存。 

5、强引用置为null,会不会被回收? 

不会立即释放对象占用的内存。 如果对象的引用被置为null,只是断开了当前线程栈帧中对该对象的引用关系,

而垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点(safe point)或安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在 finalize方法中恢复引用 )。只有确定了对象无法恢复引用的时才会清除对象内存。

一.基础知识?
1.Android下的数据存储方式有那些?
1)内部存储,直接存储在内部文件中
2)外部存储,首先要判断外部存储条件是否可用,然后进行存储
3)SP存储,底层是Xml实现的,以键值对形式存储内部的数据,适宜于轻量级的存储,存储的数据类型有,boolean,String,int
4)数据库存储,SQlite存储,轻量级的数据库,强大的增删改查功能
5)内容提供者,ContentProvider,将自己愿意暴露的一部分数据供外部使用操作
6)网络存储,等等
Sharepreference 线程安全问题?
官方文档明确指出,SharedPreferences不支持多线程,进程也是不安全的
如果想要实现线程安全需重新实现其接口,如下
prvite static final class SharedPreferenceImpl implements SharePreference{}
假设在多进程访问SharePreferences的情况下,该如何保证进程安全和共享数据?
解决办法就是:将需要共享数据的字段提出来统一存储到一个文件中。

2.对象序列化:
为什么要序列化?
1)永久性保存对象,保存对象的字节序列到本地文件中;
2)通过序列化对象在网络中传递对象;
3)通过序列化在进程间传递对象。
在Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口简单,声明即可,而实现Parcelable接口复杂,但效率更高,推荐用这种方法提高性能。两种实现方式依旧是贴url,方便大家快速查询
两种序列化相关
既然Google推荐Parcelable这种序列化,在这里,推荐一键生成序列化的插件,
在Android Studio里面搜索插件,如下图,写起序列化(根本不用你写)。

posted on 2022-04-28 21:48  左手指月  阅读(70)  评论(0编辑  收藏  举报