【问题标题】:Null pointer error when passing Parcelable data传递 Parcelable 数据时出现空指针错误
【发布时间】:2012-12-24 06:10:22
【问题描述】:

我试图在两个活动之间传递一个订单对象。此对象包含 MenuItems 的 ArrayList。 Order 的类如下:(它实现了 parcelable 接口)。

public class Order extends ArrayList <MenuItem> implements Parcelable {

private int covers;
private int table;
//To hold MenuItems
private ArrayList<MenuItem> items;

public Order(){

}

public static final Parcelable.Creator<Order> CREATOR = new Parcelable.Creator<Order>() {

    @Override
    public Order createFromParcel(Parcel source) {
        return new Order(source);
    }

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


};

public Order(int covers, int table, ArrayList<MenuItem> items) {
    super();
    this.covers = covers;
    this.table = table;
    this.items = items;
}

public int getCovers() {
    return covers;
}

public void setCovers(int covers) {
    this.covers = covers;
}

public int getTable() {
    return table;
}

public void setTable(int table) {
    this.table = table;
}

public ArrayList<MenuItem> getItems() {
    return items;
}

public void setItems(ArrayList<MenuItem> items) {
    this.items = items;
}

//add menu item to order
public void addToOrder(MenuItem m){
    items.add(m);
}

//remove menu item from order
public void removeFromOrder(MenuItem m){
    items.remove(m);
}


public Order(Parcel source) {
    readFromParcel(source);

}

private void readFromParcel(Parcel source) {

    this.clear();

    //read the size of the list
    int size = source.readInt();

    //Remember order of items written into the Parcel. Important here.
    for(int i = 0; i < size; i ++){
        MenuItem item = new MenuItem();
        item.setName(source.readString());
        item.setPrice(source.readDouble());
        this.add(item);
}

}

@Override
public void writeToParcel(Parcel dest, int arg1) {
        int size = this.size();

                dest.writeInt(size);

                for(int i = 0; i < size; i ++){
                    MenuItem item = this.get(i);
                    dest.writeString(item.getName());
                    dest.writeDouble(item.getPrice());

                }

            }

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

}

当我的活动开始时,我创建一个新的订单项目并将其放入 Intent 以发送到下一个活动。当我单击按钮开始新活动时,出现以下错误:

java.lang.RuntimeException:无法启动活动 ComponentInfo{com.example.waitron5/com.example.waitron5.SectionsActivity}:java.lang.NullPointerException

下面是我在 MainActivity.java 中用于将对象放入 Intent 的代码。

//Order object to hold details about order for duration of session
Order order;
ArrayList<Order> orderList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //As soon as app is started up create an order object.
    order = new Order();
    orderList = new ArrayList<Order>();
    orderList.add(order);

    //reference to button and add listeners
    orderBtn = (Button)findViewById(R.id.orderBtn);
    orderBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Create a new intent and start up the sections activity...
            i = new Intent(v.getContext(), SectionsActivity.class);
            i.putExtra("data", (ArrayList<Order>)orderList);
            startActivity(i);
        }
    });

}

下面是我在 SectionsActivity.java 中用于从 Intent 中检索我的对象的代码。

//Get order information
public void getOrderData(){
    i = getIntent();
    if(i != null && i.hasExtra("data")){
        Toast.makeText(this.getApplicationContext(), "recieved", Toast.LENGTH_SHORT).show();
        order = i.getParcelableExtra("data");
        int size = order.size();
        Toast.makeText(this.getApplicationContext(), String.valueOf(size), Toast.LENGTH_SHORT).show();
    }
}

有谁知道我为什么会收到这个错误。我知道这是因为它找不到可包裹的对象,我只是不知道我应该如何修复它!非常感谢。

编辑:我认为问题出在这段代码中:

@Override
public void writeToParcel(Parcel dest, int flags) {
        int size = this.size();
                dest.writeInt(size);
                for(int i = 0; i < size; i ++){
                    MenuItem item = this.get(i);
                    dest.writeString(item.getName());
                    dest.writeDouble(item.getPrice());

                }

            }

记录 CAT 错误

01-09 23:41:23.706:E/AndroidRuntime(22717):致命异常:主要 01-09 23:41:23.706: E/AndroidRuntime(22717): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.example.waitron5/com.example.waitron5.SectionsActivity}: java.lang.NullPointerException 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.ActivityThread.access$600(ActivityThread.java:141) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.os.Handler.dispatchMessage(Handler.java:99) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.os.Looper.loop(Looper.java:137) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.ActivityThread.main(ActivityThread.java:5039) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 java.lang.reflect.Method.invokeNative(Native Method) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 java.lang.reflect.Method.invoke(Method.java:511) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 01-09 23:41:23.706:E/AndroidRuntime(22717):在 dalvik.system.NativeStart.main(本机方法) 01-09 23:41:23.706:E/AndroidRuntime(22717):由:java.lang.NullPointerException 引起 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 com.example.waitron5.SectionsActivity.getOrderData(SectionsActivity.java:113) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 com.example.waitron5.SectionsActivity.onCreate(SectionsActivity.java:44) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.Activity.performCreate(Activity.java:5104) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080) 01-09 23:41:23.706: E/AndroidRuntime(22717): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144) 01-09 23:41:23.706: E/AndroidRuntime(22717): ... 11 更多

记录猫警告

*01-09 23:41:23.676:W/Bundle(22717):关键数据预期 Parcelable,但值为 java.util.ArrayList。已返回默认值。 01-09 23:41:23.686:W/Bundle(22717):尝试强制转换生成的内部异常: 01-09 23:41:23.686: W/Bundle(22717): java.lang.ClassCastException: java.util.ArrayList 不能转换为 android.os.Parcelable 01-09 23:41:23.686: W/Bundle(22717): 在 android.os.Bundle.getParcelable(Bundle.java:1171) 01-09 23:41:23.686: W/Bundle(22717): 在 android.content.Intent.getParcelableExtra(Intent.java:4330) 01-09 23:41:23.686: W/Bundle(22717): 在 com.example.waitron5.SectionsActivity.getOrderData(SectionsActivity.java:112) 01-09 23:41:23.686: W/Bundle(22717): 在 com.example.waitron5.SectionsActivity.onCreate(SectionsActivity.java:44) *

【问题讨论】:

  • 也许使用 putParcelableArrayListExtra() 将 MenuItem 的 ArrayList 作为额外的传递会更简单
  • 使用调试,并发布你得到 NullPointerException 的哪一行。
  • 在之前的项目中我是这样做的。但是由于各种原因,最好将此列表包装在另一个类中。它在上一个项目中运行良好。我认为我这样做的方式是创建另一个层,我没有正确访问它。

标签: android android-intent nullpointerexception runtime-error parcelable


【解决方案1】:

我设法解决了我的问题。问题是 Order 类正在实现 Parcelable 。但是,因为它包含一个 MenuItem 列表,所以 MenuItem 类也需要实现 Parcelable 接口。

一旦我这样做了,问题就解决了。

【讨论】:

    【解决方案2】:

    查看完整的 LogCat 堆栈跟踪以了解确切错误发生的位置会非常有帮助,但我可以立即看到一个潜在问题。

    你的默认构造函数不会调用超级构造函数:

    public Order(){
    
    }
    

    所以当writeToParcel() 被调用时,你会尝试从可能是空列表中获取值。

    MenuItem item = this.get(i); // You never initialized the super class...
    

    【讨论】:

    • 我按照你说的插入了超级构造函数。不幸的是,它没有解决问题。我感觉它可能与我添加到问题中的代码有关。
    • 你认为它可能是这样的。我的 Order 对象实现 Parcelable 接口。在将其放入 Intent 之前,我将其放入另一个 ArrayList。也许是因为这没有实现 Parcelable 接口,所以没有任何东西传递给新活动?
    • 这个java.lang.ClassCastException: java.util.ArrayList cannot be cast to android.os.Parcelable 引导我到i.putExtra("data", (ArrayList&lt;Order&gt;)orderList); 你应该使用i.putParcelableArrayListExtra("data", orderList); 并与匹配的getParcelableArrayListExtra("data") 一起阅读它。
    • 我会玩弄代码并实施您的建议。感谢您的帮助。
    【解决方案3】:

    更改i = getIntent();

    通过

    i = getIntent().getCharSequenceArrayListExtra("data");
    

    更新以获取 ArrayList

    【讨论】:

    • 另外,如果i 不是String (因为它看起来是Intent),代码甚至不会编译。
    猜你喜欢
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多