【问题标题】:NullPointerException received when calling Bundle.getParcelable调用 Bundle.getParcelable 时收到 NullPointerException
【发布时间】:2014-08-23 18:37:52
【问题描述】:

我有一个问题想解决几个小时,但无法解决,我需要一些帮助。我正在尝试从 Login 活动中检索 URL 字符串并尝试使用 parcelable 对象将其传递给 Main 活动,但我在 getParcelable 方法上收到 NullPointerException。

以下是创建 URL parcelable 对象并将其放入 Intent 并调用 Main 活动的代码

 public void onGetPremiumURLCompletion(List<String> urls){
    String[] urlList = new String[urls.size()];
    for (int i = 0; i < urls.size(); i++) {urlList[i] = urls.get(i);}
    URL urlParcelable = new URL(urlList);
    for (int i = 0; i < urlParcelable.getUrls().length; i++) {Log.w("url from parcelable",urlParcelable.getUrls()[i]);}
    Intent intent = new Intent(this,Home.class);
    intent.putExtra("PremiumURLList",urlParcelable);
    progress.dismiss();
    startActivity(intent);

}

以下是URL parcelable类

public class URL implements Parcelable {
private String[] urls;

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

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

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

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

private URL(Parcel in) {
    in.readStringArray(urls);
}

public URL(String[] urlList){
    urls = urlList;
}

public String[] getUrls() {
    return urls;
}}

这是我从 Intent 接收 Parcelable 对象的方式。

Bundle b = getIntent().getExtras();
    URL urlList = b.getParcelable("PremiumURLList");

我在 getParcelable 行上收到以下错误

Caused by: java.lang.NullPointerException
        at android.os.Parcel.readStringArray(Parcel.java:962)
        at com.rayat.pricewiz.entity.URL.<init>(URL.java:33)
        at com.rayat.pricewiz.entity.URL.<init>(URL.java:9)
        at com.rayat.pricewiz.entity.URL$1.createFromParcel(URL.java:14)
        at com.rayat.pricewiz.entity.URL$1.createFromParcel(URL.java:12)
        at android.os.Parcel.readParcelable(Parcel.java:2104)
        at android.os.Parcel.readValue(Parcel.java:2013)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
        at android.os.Bundle.unparcel(Bundle.java:249)
        at android.os.Bundle.getParcelable(Bundle.java:1206)
        at com.rayat.pricewiz.view.activity.tabhome.Home.onCreate(Home.java:72)
        at android.app.Activity.performCreate(Activity.java:5426)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)

请帮忙。

谢谢

【问题讨论】:

    标签: java android android-intent bundle parcelable


    【解决方案1】:

    你的问题在这里:

    private URL(Parcel in) {
        in.readStringArray(urls);
    }
    

    urls 此时为空,readStringArray(String[]) 方法需要一个非空参数,并且与生成的读取数组的长度相同。我发现该方法几乎没用,因为除非您事先知道数组的固定大小,否则它实际上不起作用。或者,我建议你使用createStringArray():

    private URL(Parcel in) {
        urls = in.createStringArray();
    }
    

    【讨论】:

      【解决方案2】:

      我遇到了问题并试图了解原因。我们必须检查代码才能理解。

      如您所见,writeStringArray 检查可空值,然后将数组的大小作为 int 值保存到 parcelable 中(否则 -1 值被写入为整数)。

      public final void writeStringArray(@Nullable String[] val) {
          if (val != null) {
              int N = val.length;
              writeInt(N);
              for (int i=0; i<N; i++) {
                  writeString(val[i]);
              }
          } else {
              writeInt(-1);
          }
      }
      

      readStringArray 正在使用 @NonNull 参数。所以它可能会抛出异常(如果你的数组为空)。

      public final void readStringArray(@NonNull String[] val) {
              int N = readInt();
              if (N == val.length) {
                  for (int i=0; i<N; i++) {
                      val[i] = readString();
                  }
              } else {
                  throw new RuntimeException("bad array lengths");
              }
          }
      

      最后,您可以看到 createStringArray 方法首先读取数组的大小。然后读取数组的每个字符串(在其中使用 nativeReadString)。

       @Nullable
          public final String[] createStringArray() {
              int N = readInt();
              if (N >= 0) {
                  String[] val = new String[N];
                  for (int i=0; i<N; i++) {
                      val[i] = readString();
                  }
                  return val;
              } else {
                  return null;
              }
          }
      

      所以你可以:

      1. 检查您的数组是否为空并使用 writeStringArray
      2. 改用 createStringArray,正如@kevin 建议的那样

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-29
        • 2015-02-13
        • 2012-01-21
        相关资源
        最近更新 更多