包含抽象类和派生类的Parcelable构造函数的问题

时间:2020-06-25 18:49:23

标签: java android inheritance constructor parcelable

我有一个抽象类及其子类,并且我想通过intent.putExtra(String, Parcelable);将子类通过一个活动传递给另一个活动,接收Intent的活动将接受任何包裹,因为它是扩展抽象类的对象。 我在抽象类和子类中都实现了Parcelable的实现:

public abstract class MyAbstractClass implements Parcelable{
private double dField;
private Integer stringResource;
private MyEnum objEnumType;

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        //TODO Age
        parcel.writeDouble(dField);        parcel.writeString(this.objEnumType.toString());
        parcel.writeInt(stringResource);
    }

    public static final Parcelable.Creator<MyAbstractClass> CREATOR = new Creator<MyAbstractClass>() {
        @Override
        public MyAbstractClass createFromParcel(Parcel parcel) {
            return null;
        }

        @Override
        public MyAbstractClass[] newArray(int i) {
            return new MyAbstractClass[0];
        }
    };

    protected MyAbstractClass(Parcel in){
       dField = in.readDouble();
       this.objEnumType = MyEnum.valueOf(in.readString());
       stringResource = in.readInt();
    }
}

在子类中:

public class MyChildClass extends MyAbstractClass{
    public int describeContents(){
        return 0;
    }

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

    public static final Parcelable.Creator<MyChildClass> CREATOR = new Creator<MyChildClass>() {
        @Override
        public MyChildClass createFromParcel(Parcel parcel) {
            return null;
        }

        @Override
        public MyChildClass[] newArray(int i) {
            return new MyChildClass[0];
        }
    };

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

在FirstActivity中,我写了包裹,但我得到了与MyChildClass的构造函数有关的错误:

    MyChildClass objChildClass = new MyChildClass();   //I got an error here, expecting a Parcel object?!
    Intent intent = new Intent(this,SecondActivity.class);
    intent.putExtra("extraParcelable",objChildClass);
    startActivity(intent);

根据Android Studio,MyChildClass期望使用MyChildClass的Parcel参数,但是如果我想通过Intent发送此类,如何传递Parcel?

编辑

我在MyChildClass和MyAbstractClass中都添加了一个空的构造函数:

MyChildClass(){super()}

在MyAbstractClass中:

MyAbstractClass(){}

在FirstActivity中,我添加了:

objChildClass.setDField = 2.5;
objChildClass.setObjEnumType = MyEnum.Type1;
objChildClass.setStringResource = getString(R.string.app_name);
Intent intent = new Intent(this,SecondActivity.class);
intent.putExtra("extraParcelable",objChildClass);
startActivity(intent);

在SecondActivity中:

class SecondActivity : AppCompatActivity() {
     private val lbResult by lazy {findViewById<TextView>(R.id.lb_result)}
     private val objReceived by lazy {intent?.extras?.getParcelable<MyAbstractClass>("extraParcelable")}

     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //
        //...
        //
        lbResult.text = objReceived?.dField.toString()  //I get a null here
      }
}

通过lbResults我得到一个空值。当我使用intent.putExtras(String,Double)时,代码运行良好,但是如果我使用空构造函数,则现在使用parcelable为null。否则,我会收到想要将Parcel作为构造函数传递的错误,(如我上面所述)

3 个答案:

答案 0 :(得分:1)

在MyChildClass和MyAbstractClass中创建一个空的构造函数

答案 1 :(得分:0)

protected构造函数将用于在接收端读取包裹。

您还需要一些公共构造函数(很可能带有参数)来初始化您的对象,这样您就可以首先打包数据。

答案 2 :(得分:0)

实施Parcelable时遇到的问题是由于在处理Parcelables时我忽略了有关构造函数的简单错误:

  • 首先,如果实现Parcelable的类没有构造函数,则必须与接收Parcel的构造函数一起为Parcelable类创建一个构造函数。否则,Android Studio或编译器将抱怨未将Parcel作为参数提供(因为该类中唯一的构造函数需要一个Parcel对象)。
public MyChildClass(Parcel parcel){
    super(parcel);
}
public MyChildClass(){super();}

我还必须匹配超类的构造函数:

protected MyAbstractClass(Parcel in){
   dField = in.readDouble();
   this.objEnumType = MyEnum.valueOf(in.readString());
   stringResource = in.readInt();
}
protected MyAbstractClass(){}
  • 第二,必须在createFromParcel内部的Parcelabe.Creator CREATOR方法中调用接收Parcel对象的构造函数。这是我的第二个错误。 Android Studio自动生成的Parcelable.Creator仅将return null放入这种方法。
    public static final Parcelable.Creator<MyChildClass> CREATOR = new Creator<MyChildClass>() {
        @Override
        public MyChildClass createFromParcel(Parcel parcel) {
            return new MyChildClass(parcel);   //It needs to replace the default `return null` by the instance of the class calling the constructor to pass the Parcel object
        }
        @Override
        public MyChildClass[] newArray(int i) {
            return new MyChildClass[0];
        }
    };
  • 第三:由于public T createFromParcel中的方法Parcelable.Creator CREATOR需要一个类的实例,因此我从MyAbstractClass中删除了Parcelable.Creator CREATOR,因为作为抽象类,我无法在其中创建任何实例

现在,我可以将活动的派生类传递给活动而没有null或抱怨宗地未通过构造函数传递

相关问题