如何将包含 Base64 字符串的 ArrayList 从 recyclerview 传递给另一个 activity

How to pass ArrayList that contains Base64 String to another activity from recyclerview

我正在做一个项目,我需要创建图像预览 Functionality.For 我已经创建了一个 recyclerview,我在其中传递位图的 ArrayList 并将其显示在 recyclerview.Now 我正在转换它arraylist 转换为 base64 字符串数组,并希望使用 parcelable 将该 arraylist 传递到新的 activity 中。 但我收到 TransactionTooLarge Execption。

是否有另一种方法将数组传递给另一个activity?

这是我的适配器

public class ImageListAdapter extends RecyclerView.Adapter<ImageListAdapter.ViewHolder> {

    private ArrayList<UploadImageModel> mBitmapArray;
    private Context context;
    private UploadImageModel mUploadImageModel;
    private ArrayList<Base64ArrayModel> mBase64ArrayList;
    private Base64ArrayModel mBase64ArrayModel;

    public ImageListAdapter(ArrayList<UploadImageModel> mBitmapArray, ArrayList<Base64ArrayModel> mBase64ArrayList, Context context) {
        this.mBitmapArray = mBitmapArray; //Here i am getting arraylist that contains bitmaps
        this.context = context;
    }

    @Override
    public ImageListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemView = LayoutInflater.from(context).inflate(R.layout.image_set, null);
        ViewHolder holder = new ViewHolder(itemView);
        return holder;
    }

    @Override
    public void onBindViewHolder(ImageListAdapter.ViewHolder holder, int position) {
        mUploadImageModel = mBitmapArray.get(position);

        holder.UploadImageView.setImageBitmap(mUploadImageModel.getUploadImageBitmap());

        holder.UploadImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent openPreviewActivity = new Intent(context, PreviewActivity.class);
                openPreviewActivity.putParcelableArrayListExtra("myImageList",encodeList());
                context.startActivity(openPreviewActivity);

            }
        });
    }

    @Override
    public int getItemCount() {
        return mBitmapArray.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        public ImageView UploadImageView;

        public ViewHolder(View itemView) {
            super(itemView);
            UploadImageView = (ImageView) itemView.findViewById(R.id.UploadImageView);
        }
    }

    private ArrayList<Base64ArrayModel> encodeList() {

        mBase64ArrayList = new ArrayList<>();
        for (int i = 0; i < mBitmapArray.size(); i++) {
            mBase64ArrayList.add(new Base64ArrayModel(ConstantFunction.encodeToBase64(mBitmapArray.get(i).getUploadImageBitmap(), Bitmap.CompressFormat.JPEG, 100)));
        }
        return mBase64ArrayList;
    }
}

我使用的模型如下

public class Base64ArrayModel implements Parcelable {

    public String mBase64BitmapString;

    public String getmBase64BitmapString() {
        return mBase64BitmapString;
    }

    public void setmBase64BitmapString(String mBase64BitmapString) {
        this.mBase64BitmapString = mBase64BitmapString;
    }

    public Base64ArrayModel(String mBase64BitmapString)
    {
        this.mBase64BitmapString=mBase64BitmapString;
    }

    protected Base64ArrayModel(Parcel in) {
        mBase64BitmapString = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mBase64BitmapString);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Base64ArrayModel> CREATOR = new Parcelable.Creator<Base64ArrayModel>() {
        @Override
        public Base64ArrayModel createFromParcel(Parcel in) {
            return new Base64ArrayModel(in);
        }

        @Override
        public Base64ArrayModel[] newArray(int size) {
            return new Base64ArrayModel[size];
        }
    };
}

我如何将那个 arrayList 传递给新的 activity?

来自doc,

During a remote procedure call, the arguments and the return value of the call are transferred as Parcel objects stored in the Binder transaction buffer. If the arguments or the return value are too large to fit in the transaction buffer, then the call will fail and TransactionTooLargeException will be thrown.

The Binder transaction buffer has a limited fixed size, currently 1Mb, which is shared by all transactions in progress for the process. Consequently this exception can be thrown when there are many transactions in progress even when most of the individual transactions are of moderate size.

所以,这基本上意味着,您正在尝试传递大小大于 Binder Transaction Buffer 可以包含的数据。为了克服这个问题,您必须减小数据的大小(base64String 大小,适合您的情况)。我可以看到你有这个 ConstantFunction.encodeToBase64(mBitmapArray.get(i).getUploadImageBitmap(), Bitmap.CompressFormat.JPEG, 100) 将位图编码为 base64String 的方法,您已将 100 作为压缩级别。在您的实现中,如果您使用 bitmap.compress 方法压缩位图,请尝试减少数量。数字越少,压缩后的质量就越差,因此,您最终会得到小尺寸的 base64String。

你可以使用 EventBus :

  1. 创建事件,然后 post arraylist 并在任何你想要的地方接收..

例如

    compile 'org.greenrobot:eventbus:3.0.0'

//create class
    public class Base64Event {
        public final List< Base64ArrayModel > base64Array;
        public Base64Event(List< Base64ArrayModel > base64Array){

    }
    }

//Post

  EventBus.getDefault().postSticky(new Base64Event(base64Array));

//接收者在activity

  @Subscribe(threadMode = ThreadMode.MAIN)
    public void anyName(Base64Event event) {
      event. base64Array //here is the data passed
    }

首先,将此行添加到清单文件中。

android:largeHeap="true"

因为同时一次你的交易量太大了。所以让一个单身人士class喜欢。这不是我想建议使用数据库的首选方式,但如果你没有其他选择,这个更适合你。

public class DataTransactionModel {

    private static volatile DataTransactionModel instance = null;
    private ArrayList<Base64ArrayModel> list = null;

    private DataTransactionModel() {
    }

    public static synchronized DataTransactionModel getInstance() {
        if (instance == null) {
            synchronized (DataTransactionModel.class) {
                if (instance == null) {
                    instance = new DataTransactionModel();
                }
            }
        }
        return instance;
    }

    public Bitmap getList() {
        return list;
    }

    public void setList(Bitmap bitmap) {
        this.bitmap = list;
    }
}

将数据设置到此单例中 class,然后借助单例 class 方法获取图像列表。

    ...

    @Override
        public void onBindViewHolder(ImageListAdapter.ViewHolder holder, int position) {
            mUploadImageModel = mBitmapArray.get(position);

            holder.UploadImageView.setImageBitmap(mUploadImageModel.getUploadImageBitmap());

            holder.UploadImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    DataTransactionModel model = DataTransactionModel.getInstance();
                    model.setList(encodeList());
                    Intent openPreviewActivity = new Intent(context, PreviewActivity.class);
                    context.startActivity(openPreviewActivity);

                }
            });
        }