15

First of all i have check this answer.

What i am trying to do is extending Location class calling it LocationPlus which has some member variables. functionality i am trying to achieve is pass the object of LocationPlus class from one activity to another.

Here is my CREATOR

public static final Parcelable.Creator<LocationPlus> CREATOR = new Parcelable.Creator<LocationPlus>() {
    @Override 
    public LocationPlus createFromParcel(Parcel source) {
        return new LocationPlus(source);
    }
    @Override 
    public LocationPlus[] newArray(int size) {
        return new LocationPlus[size];
    }
};

problem i am facing is this error

Implicit super constructor Location() is undefined. Must explicitly invoke another constructor

when trying to write constructor

public LocationPlus(Parcel in) {

Someone in comment ask me to post LocationPlus class so here it is

public class LocationPlus extends Location{

    private int mBattery = -1;

    public LocationPlus(String locationName) {
        super(locationName);
    }

    public LocationPlus(Location location) {
        super(location);
    }

    public int getmBattery() {
        return mBattery;
    }

    public void setmBattery(int mBattery) {
        this.mBattery = mBattery;
    }
    @Override
    public int describeContents() {
        return 0;
    }

    public static final Parcelable.Creator<LocationPlus> CREATOR = new Parcelable.Creator<LocationPlus>() {
        @Override 
        public LocationPlus createFromParcel(Parcel source) {
            return new LocationPlus(source);
        }
        @Override 
        public LocationPlus[] newArray(int size) {
            return new LocationPlus[size];
        }
    };

    @Override
    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeInt(mBattery);
    }

    public LocationPlus(Parcel in) {
        mBattery =in.readInt();
    }
}
Community
  • 1
  • 1
Akram
  • 7,548
  • 8
  • 45
  • 72

4 Answers4

39

Parcelable, the Speed King

According to google engineers, this code will run significantly faster. One of the reasons for this is that we are being explicit about the serialization process instead of using reflection to infer it. It also stands to reason that the code has been heavily optimized for this purpose.

public abstract class BaseClass implements Parcelable {

    public String FullName;
    public boolean IsValidUser;
    public String UserName;


    public BaseClass () {
    }


    protected BaseClass(Parcel in) {
        FullName = in.readString();
        IsValidUser = in.readByte() != 0;
        UserName = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(FullName);
        dest.writeByte((byte) (IsValidUser ? 1 : 0));
        dest.writeString(UserName);
    }
}

Child class will be as follows with usage of list adding into parcelable object:

public class DerivedClass extends BaseClass {

    public boolean IsSuccess;
    public String Message;
    public List<AnotherClass> AnotherClassObj;


    public DerivedClass () {
        super();
    }

    protected DerivedClass(Parcel in) {
        super(in);
        AnotherClassObj = new ArrayList<AnotherClass>();
        IsSuccess = in.readByte() != 0;
        Message = in.readString();
        AnotherClassObj = in.readArrayList(AnotherClass.class.getClassLoader());
    }

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeByte((byte) (IsSuccess ? 1 : 0));
        dest.writeString(Message);
        dest.writeList(AnotherClassObj);
    }

    public int describeContents() {
        return 0;
    }
}

Another child class :

public class AnotherClass extends BaseClass {
    public AnotherClass() {
        super();
    }

    protected AnotherClass(Parcel in) {
        super(in);
    }

    public int describeContents() {
        return 0;
    }

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

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

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

In Activity:

 Intent intent = new Intent(LoginActivity.this, MainActivity.class);
 intent.putExtra("UserObject", parcelableObject);
 startActivity(intent);
 finish();

In receiving activity:

Bundle extras = getIntent().getExtras();
 if (extras != null) {
      userObject = extras.getParcelable("UserObject");
 }
Community
  • 1
  • 1
Min2
  • 10,751
  • 2
  • 19
  • 22
  • Why you didn't create a `Creator` in your base class? Please explain. `public static final Creator CREATOR = new Creator()` – Muhammad Saqib Jan 09 '20 at 15:34
  • 1
    @MuhammadSaqib The `CREATOR` object is used to generate instances of the Parcelable class from a Parcel. Since `BaseClass` is abstract it can't be instantiated. Btw careful when both base and subclass can be instantiated as a `Parcel`. Bad stuff will happen when you mix them together during writing and reading. See here for more: https://idlesun.blogspot.com/2012/12/android-parcelable-example-3-subclass.html – MattSchmatt Mar 05 '21 at 17:34
5

Hi I've do research a lot about this, but I couldn't find useful anything. I try solution below and it worked for me.

Let say your super class has only int variable named "mData".

public class Location implements Parcelable {
 protected int mData;

 public int describeContents() {
     return 0;
 }

 public void writeToParcel(Parcel out, int flags) {
     out.writeInt(mData);
 }

 public static final Parcelable.Creator<Location> CREATOR
         = new Parcelable.Creator<Location>() {
     public Location createFromParcel(Parcel in) {
         return new Location(in);
     }

     public Location[] newArray(int size) {
         return new Location[size];
     }
 };

 private Location(Parcel in) {
     mData = in.readInt();
 }

}

Then, your extended class has only int variable named "mBattery".

public class LocationPlus extends Location {
 protected int mBattery;

 public int describeContents() {
     return 0;
 }

 public void writeToParcel(Parcel out, int flags) {
     out.writeInt(mBattery);
 }

 public static final Parcelable.Creator<LocationPlus> CREATOR
         = new Parcelable.Creator<LocationPlus>() {
     public LocationPlus createFromParcel(Parcel in) {
         return new LocationPlus(in);
     }

     public LocationPlus[] newArray(int size) {
         return new LocationPlus[size];
     }
 };

 private LocationPlus(Parcel in) {
     mBattery = in.readInt();
 }

}

So far, LocationPlus works fine. But we don't set variable of super class. Firstly, I set super class' variables on extended class with super(..) method. But it didn't work.

private LocationPlus(Parcel in) {
     super(in);
     mBattery = in.readInt();
 }

Instead of code above, you should set all super class' variables explicitly. Super class' variables should be protected. Final constructor should be like this:

private LocationPlus(Parcel in) {
     mData = in.readIn();
     mBattery = in.readInt();
 }

and writeToParcel method should be like this:

public void writeToParcel(Parcel out, int flags) {
     out.writeIn(mData);
     out.writeInt(mBattery);
 }
farukcankaya
  • 544
  • 7
  • 11
  • Doing super(in) in the LocationPlus constructor should work, you just need to make sure to also do super.writeToParcel(out, flags) in writeToParcel. – SilentByte Mar 05 '18 at 18:26
1

Try this solution:

public static final Parcelable.Creator<LocationPlus> CREATOR =
    new Parcelable.Creator<LocationPlus>() {
    @Override
    public LocationPlus createFromParcel(Parcel in) {

        Location l = Location.CREATOR.createFromParcel(in);
        LocationPlus lp = new LocationPlus(l);

        lp.mBattery= in.readInt();

        return lp;
    }

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

@Override
public void writeToParcel(Parcel parcel, int flags) {
    super.writeToParcel(parcel, flags);
    parcel.writeInt(mBattery);

}
Hufnal
  • 9
  • 1
0

According to the Android docs, there isn't a Location() constructor for the Location class. When initializing your LocationPlus class, you need to call either super(String provider) or super(Location l).

Edit: Corrected syntax

(See Location Android Doc)

Brian
  • 1,436
  • 8
  • 18
  • Thanks for your valuable time and answer Brian i have seen the Docs i am looking for any work around for this problem. – Akram Jul 18 '13 at 14:19
  • What you need to do is include a call to a `super(String provider)` or `super(Location l)` constructor in the `LocationPlus(Parcel in)` method. – Brian Jul 18 '13 at 14:31