使用Parcelable将包含对象列表的对象传递到另一个活动

5
我有一个名为WorkerActivity的活动,在其中有一些工人的列表,我正在尝试将所点击的工人对象传递给我的WorkerDetailActivity。我相对于Java和Android是比较新手,因此我在寻找可能的解决方案时,在大多数答案中都建议不要使用序列化,而应该使用Parcelable。我试图按照这里提出的方式进行操作:
How to pass a parcelable object that contains a list of objects?

代码的最后三行,in.readList(machinePossession, null);部分显示了以下错误:

类型不匹配:无法从void转换为List<Machine>

我不知道该如何处理这个问题,并且非常乐意接受任何建议。
为了使发布的代码干净整洁,我删除了包以及所有构造函数、设置器和获取器。
import java.util.ArrayList;
import java.util.List;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

public class Worker implements Parcelable{

private String workerID;
private String workerPersonnelNR;
private String workerLastName;
private String workerName;
private String workerCategory;
private String historyName;
private String historyID;
private String historyFrom;
private String historyTo;
private String historyActive;
private String historyDays;
public List<Machine> machinePossession = new ArrayList<Machine>();
public List<Machine> machinePossibility = new ArrayList<Machine>();
public List<Machine> machineHistory = new ArrayList<Machine>();


public String error;

public static class WorkerWrapper{

    public List<Worker> workers;

    public WorkerWrapper(List<Worker> workers) {
        this.workers = workers;
    }
}

public Worker(){
    //default constructor
}

    /*REMOVED CONSTRUCTORS / SETTERS / GETTERS */

//parcel
public void writeToParcel(Parcel dest, int flags) {
    Log.v("", "writeToParcel..." + flags);
    dest.writeString(workerID);
    dest.writeString(workerPersonnelNR);
    dest.writeString(workerLastName);
    dest.writeString(workerName);
    dest.writeString(workerCategory);
    dest.writeString(historyName);
    dest.writeString(historyID);
    dest.writeString(historyFrom);
    dest.writeString(historyTo);
    dest.writeString(historyActive);
    dest.writeString(historyDays);        
    dest.writeList(machinePossession);
    dest.writeList(machinePossibility);
    dest.writeList(machineHistory);
}

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

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

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

private Worker(Parcel in) {
    workerID = in.readString();
    workerPersonnelNR = in.readString();
    workerLastName = in.readString();
    workerName = in.readString();
    workerCategory = in.readString();
    historyName = in.readString();
    historyID = in.readString();
    historyFrom = in.readString();
    historyTo = in.readString();
    historyActive = in.readString();
    historyDays = in.readString(); 
    machinePossession = in.readList(machinePossession, null);
    machinePossibility = in.readList(machineHistory, null);
    machineHistory = in.readList(machineHistory, null);
    }
}

编辑:

感谢 @Archie.bpgc
为了消除错误,您需要像这样编写代码:

private Worker(Parcel in) {
    workerID = in.readString();   
    ....
    historyDays = in.readString(); 
    in.readList(machinePossession, null);
    in.readList(machineHistory, null);
    in.readList(machineHistory, null);
    }

如果您只想在活动之间传递自定义对象,为什么要将其序列化...只需将其放入bundle中传递即可。请参见下面的解决方案。 - drulabs
3个回答

3

这是因为您的 machinePossession 是一个 Machine 的列表

in.readList(machinePossession, null) 返回 void

因此,在此步骤中:

machinePossession = in.readList(machinePossession, null);

您得到了以下错误:

类型不匹配:无法将void转换为List

这是因为尝试在 List<Machine> 中保留 void

参考文档readList 方法的声明如下:

public final void readList (List outVal, ClassLoader loader)

API 1 新增 从 Parcel 的当前 dataPosition() 处读取数据,将其读入现有 List 对象中,并使用给定的类加载器来加载任何包含的 Parcelable。如果类加载器为 null,则使用默认的类加载器。

因此,我认为:

in.readList(machinePossession, null);

足以满足需求。不要将其分配给List<machine>,而是使用它来读取


我觉得我还是不太明白。 所以readList想要读取一个List<Machine>,但实际上得到的是void,所以它告诉我出错了? 所以真正的问题是我的void writeToParcel没有正确地将List写入Parcel对象中传递? - Frank
请问您能否详细解释一下您上一句话的意思? - Frank
我相信readList()函数是用来将数据读入给定的(作为参数)列表中的。你可以说它类似于一个setter方法,而不是getter方法。因此,不要使用这个setter方法进行赋值,只需调用它即可,它会将数据读入你的List<machine>中。 - Archie.bpgc
谢谢!现在它不再显示错误了。它仍然抛出一个RuntimeException,但我相信这是因为我还没有完全将Parcelable编码到Machine类中。 所以我的Worker类和相关的活动现在都运行良好。 - Frank

0

我解决了一个类似的问题,即如何传递带有List字段的Parcelable,并且它对我很有效。这是一个示例(如果有帮助,请点赞):

 /**
  * Note: You have to keep an order of writing and reading
  * If you have more than one field.
  **/
 public class Test implements Parcelable {

   // Machine also implements Parcelable.
   private List<Machine> machinePossession;

   public static final Creator<Test> CREATOR = new Creator<Test>() {

      @Override
      public Test createFromParcel(Parcel in) {
         return new Test(in);
      }

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

   protected Test(Parcel in) {

      // This is a must to make sure the machinePossession isn't null.
      // Anyway, you can ignore this line If you can make sure machinePossession isn't null.
      machinePossession = new ArrayList<>();

      // You have to make Machine class implement Parceable and create a CREATOR in it.
      in.readTypedList(machinePossession, Machine.CREATOR);
   }

   @Override
   public void writeToParcel(Parcel dest, int flags) {
      // It's better to log machinePossession's info here to make suer it contains values.
      dest.writeTypedList(machinePossession);
   }

 }

0

对于这个问题,有一个非常简单的解决方案。如果你的对象所属的类实现了Parcelable或Serializable接口,那么你可以像下面这样处理:

由于你的worker类实现了Parcelable接口。

来自Activity1

Bundle bundle = new Bundle();
bundle.putParcelable("worker", workerObject);
bundle.putParcelableArray("workerArray", workerArrayObject);
bundle.putParcelableArrayList("workerArrayList", workerArrayList);
Intent i = new Intent(this, Activity2.class);
i.putExtras(bundle);
startActivity(i);

在Activity2的onCreate()方法内

Bundle bundle = getIntent().getExtras();
Worker workerObject = bundle.getParceable("worker");
Worker[] workerArray = bundle.getParceableArray("workerArray");
ArrayList<Worker> workerArrayList = bundle.getParceableArrayList("workerArrayList");

处理类型转换,你就可以开始了...

希望能帮到你


所以我尝试了你的解决方案。我让它工作了,但是没有在workerobject中包含列表。感谢您的帮助。我没有包括: bundle.putParcelableArray("workerArray", workerArrayObject); bundle.putParcelableArrayList("workerArrayList", workerArrayList); 我不明白为什么要这样做。这只是一个可以传递其他内容的示例吗? 因为列表已经在我的workerobject中了。 - Frank
我只是想展示你可以从一个活动传递所有三种类型(workerobject、workerObjectArray和workerObjectArrayList)到另一个活动。如果你只想使用其中一种,那么移除其他的bundle.put(...)即可。在获取workerObject后,使用它和所需的列表即可。 - drulabs

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