Android 与位图相关的可打包问题
Android parcelable issue relating to bitmaps
出于某种原因,有时当我的 Vehicle 对象作为 parcelable 传递给另一个对象时 activity 它会违反最大尺寸:
java.lang.RuntimeException: android.os.TransactionTooLargeException:
data parcel size 569848 bytes
然而奇怪的是,这并不是每次都会发生。在我的应用程序中,我有一张图片,当我点击它时,它会将它传递给另一个 activity。多次单击同一图像后,最终会导致该异常。我也在压缩位图。有人知道这个问题吗?
我还要注意,如果我用 30 压缩,我也会遇到同样的问题
package com.example.daniel.carbudgy.misc;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import com.example.daniel.carbudgy.R;
import com.example.daniel.carbudgy.tasks.ImageDownloaderCallback;
import com.example.daniel.carbudgy.tasks.ImageDownloaderTask;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.net.URL;
/**
* Created by daniel on 11/09/17.
*/
public class Vehicle implements Parcelable {
public interface VehicleHandler {
public void ready();
}
private int id;
private String name;
private String colour;
private String imageSrc;
private Drawable image;
private VehicleHandler handler;
public Vehicle(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
this.colour = in.readString();
this.imageSrc = in.readString();
int length = in.readInt();
byte[] buf = new byte[length];
in.readByteArray(buf);
// Convert Bitmap to Drawable:
image = new BitmapDrawable(BitmapFactory.decodeByteArray(buf, 0, length));
}
public Vehicle(JSONObject vehicle_json) throws JSONException {
JSONObject manufacture = vehicle_json.getJSONObject("manufactureModel").getJSONObject("manufacture");
JSONObject model = vehicle_json.getJSONObject("manufactureModel").getJSONObject("model");
String vehicle_name = manufacture.getString("manufacture") + " " + model.getString("model");
Integer vehicle_id = vehicle_json.getInt("vehicleId");
String image_src = vehicle_json.getJSONObject("imageUpload").getString("url");
String colour = vehicle_json.getJSONObject("colour").getString("colour");
setId(vehicle_id);
setName(vehicle_name);
setColour(colour);
setImageSrc(image_src);
image = null;
handler = null;
}
public static final Creator<Vehicle> CREATOR = new Creator<Vehicle>() {
@Override
public Vehicle createFromParcel(Parcel in) {
return new Vehicle(in);
}
@Override
public Vehicle[] newArray(int size) {
return new Vehicle[size];
}
};
public void setHandler(VehicleHandler handler) {
this.handler = handler;
}
public void load() {
try {
URL url = new URL(imageSrc);
new ImageDownloaderTask(new ImageDownloaderCallback() {
@Override
public void success(Drawable[] drawables) {
image = drawables[0];
handler.ready();
}
@Override
public void fail() {
}
}).execute(url);
} catch(Exception ex) {
throw new RuntimeException(ex);
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
public String getImageSrc() {
return imageSrc;
}
public void setImageSrc(String imageSrc) {
this.imageSrc = imageSrc;
}
public Drawable getImage() {
return image;
}
public void setImage(Drawable image) {
this.image = image;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(getId());
parcel.writeString(getName());
parcel.writeString(getColour());
parcel.writeString(getImageSrc());
ByteArrayOutputStream out = new ByteArrayOutputStream();
((BitmapDrawable)getImage()).getBitmap().compress(Bitmap.CompressFormat.PNG, 0, out);
parcel.writeInt(out.size());
parcel.writeByteArray(out.toByteArray());
}
}
Does anyone know the issue?
不要在Intent
extras中传递一个Bitmap
,在保存的实例状态Bundle
等中传递,而是传递允许对方使用位图的信息:
通过从进程中的位图缓存中提取它
通过再次从其原始源加载位图(例如,https
URL)
基于 Binder 的 IPC 事务有 1MB 的限制。该限制适用于所有未完成的交易,因此多个并发交易的合并内存使用量需要低于 1MB。因此,您看到的方差可能来自:
Bitmap
本身的不同内存占用,基于分辨率,或
改变当时正在进行的其他 IPC 事务
你的 objective 是为了确保任何这样的交易——例如在你的进程之外传递一个 Intent
——应该远不接近 1MB 的限制,所以即使有一些交易立即进行,总计未达到 1MB。
出于某种原因,有时当我的 Vehicle 对象作为 parcelable 传递给另一个对象时 activity 它会违反最大尺寸:
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 569848 bytes
然而奇怪的是,这并不是每次都会发生。在我的应用程序中,我有一张图片,当我点击它时,它会将它传递给另一个 activity。多次单击同一图像后,最终会导致该异常。我也在压缩位图。有人知道这个问题吗?
我还要注意,如果我用 30 压缩,我也会遇到同样的问题
package com.example.daniel.carbudgy.misc;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import com.example.daniel.carbudgy.R;
import com.example.daniel.carbudgy.tasks.ImageDownloaderCallback;
import com.example.daniel.carbudgy.tasks.ImageDownloaderTask;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.net.URL;
/**
* Created by daniel on 11/09/17.
*/
public class Vehicle implements Parcelable {
public interface VehicleHandler {
public void ready();
}
private int id;
private String name;
private String colour;
private String imageSrc;
private Drawable image;
private VehicleHandler handler;
public Vehicle(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
this.colour = in.readString();
this.imageSrc = in.readString();
int length = in.readInt();
byte[] buf = new byte[length];
in.readByteArray(buf);
// Convert Bitmap to Drawable:
image = new BitmapDrawable(BitmapFactory.decodeByteArray(buf, 0, length));
}
public Vehicle(JSONObject vehicle_json) throws JSONException {
JSONObject manufacture = vehicle_json.getJSONObject("manufactureModel").getJSONObject("manufacture");
JSONObject model = vehicle_json.getJSONObject("manufactureModel").getJSONObject("model");
String vehicle_name = manufacture.getString("manufacture") + " " + model.getString("model");
Integer vehicle_id = vehicle_json.getInt("vehicleId");
String image_src = vehicle_json.getJSONObject("imageUpload").getString("url");
String colour = vehicle_json.getJSONObject("colour").getString("colour");
setId(vehicle_id);
setName(vehicle_name);
setColour(colour);
setImageSrc(image_src);
image = null;
handler = null;
}
public static final Creator<Vehicle> CREATOR = new Creator<Vehicle>() {
@Override
public Vehicle createFromParcel(Parcel in) {
return new Vehicle(in);
}
@Override
public Vehicle[] newArray(int size) {
return new Vehicle[size];
}
};
public void setHandler(VehicleHandler handler) {
this.handler = handler;
}
public void load() {
try {
URL url = new URL(imageSrc);
new ImageDownloaderTask(new ImageDownloaderCallback() {
@Override
public void success(Drawable[] drawables) {
image = drawables[0];
handler.ready();
}
@Override
public void fail() {
}
}).execute(url);
} catch(Exception ex) {
throw new RuntimeException(ex);
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
public String getImageSrc() {
return imageSrc;
}
public void setImageSrc(String imageSrc) {
this.imageSrc = imageSrc;
}
public Drawable getImage() {
return image;
}
public void setImage(Drawable image) {
this.image = image;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(getId());
parcel.writeString(getName());
parcel.writeString(getColour());
parcel.writeString(getImageSrc());
ByteArrayOutputStream out = new ByteArrayOutputStream();
((BitmapDrawable)getImage()).getBitmap().compress(Bitmap.CompressFormat.PNG, 0, out);
parcel.writeInt(out.size());
parcel.writeByteArray(out.toByteArray());
}
}
Does anyone know the issue?
不要在Intent
extras中传递一个Bitmap
,在保存的实例状态Bundle
等中传递,而是传递允许对方使用位图的信息:
通过从进程中的位图缓存中提取它
通过再次从其原始源加载位图(例如,
https
URL)
基于 Binder 的 IPC 事务有 1MB 的限制。该限制适用于所有未完成的交易,因此多个并发交易的合并内存使用量需要低于 1MB。因此,您看到的方差可能来自:
Bitmap
本身的不同内存占用,基于分辨率,或改变当时正在进行的其他 IPC 事务
你的 objective 是为了确保任何这样的交易——例如在你的进程之外传递一个 Intent
——应该远不接近 1MB 的限制,所以即使有一些交易立即进行,总计未达到 1MB。