Passing Parcelable object which has a member variable which is Not parcelable(a class that belongs to third party library)

好久不见. 提交于 2021-02-11 14:13:51

问题


I'm trying to send a class's object(let's say Class X's object) as part of class that implements Parcelable. The problem that I am facing here is, Class X is a part of some library and I can not edit it to implement Parcelable or serializable.
I've checked that Class X does not implement Parcelable or serializable and we can not change as well.
Can you guys please help me here?

MainActivity:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Start the service.
        DummyParcelableObject mObj = new DummyParcelableObject(new RandomClass(2019));
        Intent serviceIntent = new Intent(MainActivity.this, SampleService.class);
        serviceIntent.putExtra("myObj", mObj);
        startService(serviceIntent);
    }
}

Dummy Parcelable class:

class DummyParcelableObject implements Parcelable {

    RandomClass mRandomClass;

    public DummyParcelableObject(RandomClass obj) {
        mRandomClass = obj;
    }

    protected DummyParcelableObject(Parcel in) {
        mRandomClass = (RandomClass) in.readValue(RandomClass.class.getClassLoader());
    }

    public static final Creator<DummyParcelableObject> CREATOR = new Creator<DummyParcelableObject>() {
        @Override
        public DummyParcelableObject createFromParcel(Parcel in) {
            return new DummyParcelableObject(in);
        }

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

    public int getRandomVar() {
        int n = 0;

        if (mRandomClass != null)
        {
            System.out.println("Anil: DummyParcelableObject: if (mRandomClass != null) is true.\n");
            n = mRandomClass.getNumb();
        }
        else
        {
            System.out.println("Anil: DummyParcelableObject: if (mRandomClass != null) is false.\n");
        }

        return n;
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

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

Class X that is part of another library:

class RandomClass{
    public static int cnt = 0;
    private int nRandomNumber = 0;
    public RandomClass(int n)
    {
        nRandomNumber = n;
    }

    public int getNumb()
    {
        return nRandomNumber;
    }
}

Service that we need to send the data to:

public class SampleService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startid) {
        DummyParcelableObject obj = intent.getParcelableExtra("mObj");
        if (obj == null) {
            System.out.println("\nAnil: ParcelableExtra is null");
        }
        else {
            System.out.println("\nAnil: ParcelableExtra is not null");
            System.out.println("\nAnil: obj.getRandomVar() = " + obj.getRandomVar());
        }

        return START_STICKY;
    }
}

回答1:


If you cannot implement Parcelable or Serializable, there is only one option left: passing the object through global state.

Using static fields

Add a static field of the type RandomClass to DummyParcelableObject, e.g. randomClassStatic. Set it just before starting the service:

// Start the service.
DummyParcelableObject mObj = new DummyParcelableObject(new RandomClass(2019));
Intent serviceIntent = new Intent(MainActivity.this, SampleService.class);
serviceIntent.putExtra("myObj", mObj);
DummyParcelableObject.randomClassStatic = mObj.getRandomClass();
startService(serviceIntent);

Then retrieve it right after the service started in onStartCommand():

DummyParcelableObject obj = intent.getParcelableExtra("mObj");
obj.setRandomClass(DummyParcelableObject.randomClassStatic);
DummyParcelableObject.randomClassStatic = null;

You would need to define getRandomClass() and setRandomClass() accordingly for getting / setting mRandomClass.

Note that this is not the safest thing to do in regard of concurrency, objects' life cycles, etc…

Using the Application class

This can only be used if you have access to an Activity or Service on both ends.

Subclass Application and add a field of type RandomClass to it. It will serves as relay. Define public methods for getting / setting this field (e.g. getRandomClass() and setRandomClass()). Do not forget to reference your subclassed Application in the manifest as described here. Before starting the service:

// Start the service.
DummyParcelableObject mObj = new DummyParcelableObject(new RandomClass(2019));
Intent serviceIntent = new Intent(MainActivity.this, SampleService.class);
serviceIntent.putExtra("myObj", mObj);
((MyApplication) getApplication()).setRandomClass(mObj.getRandomClass());
startService(serviceIntent);

Then for retrieving the object once the service started, still in onStartCommand():

DummyParcelableObject obj = intent.getParcelableExtra("mObj");
obj.setRandomClass(((MyApplication) getApplication()).getRandomClass());
DummyParcelableObject.randomClassStatic = null;

This has the benefit of not using a static field, but can still be a source of bugs if handled poorly (thread safety, no checks on nullity, …).



来源:https://stackoverflow.com/questions/56481530/passing-parcelable-object-which-has-a-member-variable-which-is-not-parcelablea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!