如何扩展实现Parcelable接口的Android类?

15
首先我检查了这个答案
我的目标是扩展Location类并将其称为LocationPlus,它具有一些成员变量。我试图实现的功能是从一个活动传递LocationPlus类的对象到另一个活动。
以下是我的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];
    }
};

我面临的问题是这个错误

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

尝试编写构造函数时

public LocationPlus(Parcel in) {

有人在评论中要求我发布LocationPlus类,所以在这里。

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();
    }
}

请发布您的LocationPlus类。 - Lucas Arrefelt
@Hasslarn的代码已发布。 - Akram
只是好奇,如果在LocationPlus中放置一个空构造函数(尝试使用空的构造函数和带有super调用的构造函数):public LocationPlus() { super() },会显示什么。很遗憾,我这台机器上没有Java,所以我无法尝试。Location构造函数可能是受保护的。 - Lucas Arrefelt
啊,LocationPlus(Parcel in)中的super(this)怎么处理? - Lucas Arrefelt
好的,这是一个冒险。我已经有一段时间没有写 Java 了。如果今天结束时你没有得到任何答案,我会回家尝试一些东西。 - Lucas Arrefelt
显示剩余2条评论
4个回答

39

Parcelable,速度之王

根据Google工程师的说法,这段代码将会运行得更快。其中一个原因是我们明确了序列化过程,而不是使用反射来推断它。这也意味着该代码已经为此目的进行了大量优化。

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);
    }
}

使用列表添加到可包含对象中时,子类将如下所示:

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;
    }
}

另一个子类

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);
    }
}

进行中:

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

在接收活动中:

Bundle extras = getIntent().getExtras();
 if (extras != null) {
      userObject = extras.getParcelable("UserObject");
 }

为什么你没有在基类中创建一个“Creator”?请解释。 public static final Creator<BaseClass> CREATOR = new Creator<BaseClass>() - Muhammad Saqib
3
@MuhammadSaqib CREATOR 对象用于从 Parcel 生成 Parcelable 类的实例。由于 BaseClass 是抽象的,因此无法实例化。另外,当基类和子类都可以作为 Parcel 实例化时,请小心在写入和读取过程中混合使用它们可能会导致问题。更多信息请参见:https://idlesun.blogspot.com/2012/12/android-parcelable-example-3-subclass.html - MattSchmatt

5

你好,我对此进行了很多研究,但是没有找到有用的内容。 我尝试了下面的解决方案,并且它对我有效。

假设您的超类只有一个名为“mData”的int变量。

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();
 }

接下来,你的扩展类只有一个名为“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();
 }

到目前为止,LocationPlus运行良好。但是我们没有设置超类的变量。首先,我使用super(..)方法在扩展类中设置了超类的变量,但它没有起作用。

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

不要使用上述代码,应该显式设置所有超类变量。超类的变量应该是受保护的。最终构造函数应该像这样:

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

而writeToParcel方法应该像这样:

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

在 LocationPlus 构造函数中执行 super(in) 应该是可行的,你只需要确保在 writeToParcel 中也执行 super.writeToParcel(out, flags)。 - SilentByte

1
尝试这个解决方案:

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);

}

0
根据Android文档,Location类中没有Location()构造函数。在初始化您的LocationPlus类时,您需要调用super(String provider)super(Location l)之一。

编辑:已更正语法

(请参见Location Android Doc)


感谢您宝贵的时间和回答,Brian。我已经看过文档了,但我正在寻找解决这个问题的任何方法。 - Akram
你需要做的是在 LocationPlus(Parcel in) 方法中调用 super(String provider)super(Location l) 构造函数。 - Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接