Search code examples
javaandroidarraylistparcelableparcel

How to get rid of implementing Parcelable for each class in android in order to use it for put extra array list


Is it possible to implement a Parcelable class one time and use it for all other class in order to pass Lists with put extra array list between activities?


Solution

  • Yes , with reflection.

    import android.os.Parcel;
    import android.os.Parcelable;
    import android.util.Log;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    
    public class ParcelableEntity implements Parcelable {
        private static final String TAG = "ParcelableEntity";
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel destination, int flags) {
    
            destination.writeString(this.getClass().getCanonicalName());
    
            for (Field field : this.getClass().getDeclaredFields()) {
                try {
                    field.setAccessible(true);
                    if (field.getType().equals(java.util.List.class)) {
                        destination.writeList((ArrayList) field.get(this));
                    } else
                        destination.writeValue(field.get(this));
                } catch (Exception err) {
                    Log.w(TAG, err.toString());
                }
    
            }
    
        }
    
        public static final Creator CREATOR = new Creator() {
            public ParcelableEntity createFromParcel(Parcel source) {
                try {
                    Object entity = Class.forName((source.readString())).newInstance();
    
                    for (Field field : entity.getClass().getDeclaredFields()) {
                        try {
                            field.setAccessible(true);
                            if (field.getType().equals(java.util.List.class)) {
                                ArrayList list = new ArrayList();
                                source.readList(list, Class.forName(field.getDeclaringClass().getName()).getClassLoader());
                                field.set(entity, list);
                            } else
                                field.set(entity, source.readValue(field.getType().getClassLoader()));
    
                        } catch (Exception err) {
                            Log.w(TAG, err.toString());
                        }
                    }
    
                    return (ParcelableEntity) entity;
    
                } catch (Exception err) {
                    return null;
                }
            }
    
            public ParcelableEntity[] newArray(int size) {
                return new ParcelableEntity[size];
            }
        };
    
    } 
    

    And now you should extend it in your class

    public class Book extends ParcelableEntity {
    
        public Long id;
        public String name;
    }
    

    And then use it

    public void onClick(View view) {
            ArrayList<book> lstBook = new ArrayList<>();
            Book b1 = new Book();
            b1.id = 1L;
            b1.name = "test 1";
            lstBook.add(b1);
            Book b2 = new Book();
            b2.id = 2L;
            b2.name = "test 2";       
            lstBook.add(b2);
    
            Intent intent = new Intent(MainActivity.this, SecondActivity.class);
            intent.putParcelableArrayListExtra("TEST", lstBook);
            startActivity(intent);
        }