图片之复习
二. 图片相关?
五.图片常见的问题
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
- Android中图片是以Bitmap(位图)形式存在,位图常见的文件格式有:.bmp .jpg .png .gif 。
- Bitmap的大小计算 = 图片的长度*图片的宽度单位像素所占用的字节数。
- 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里面搜索插件,如下图,写起序列化(根本不用你写)。