有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Parcleable extra在开始活动后不在那里

我正在尝试实现Parcleable,以便可以将其添加为额外功能(这是一项要求)

下面是类SwinImage的精简版本,它只显示相关细节,即从Parcleable派生的部分:

package com.example.kevin.imagemetadata;
import 安卓.os.Parcel;
import 安卓.os.Parcelable;

public class SwinImage implements Parcelable
{
    public SwinImage(String imageName, String location, String[] keywords, String imageDate, boolean share, String email, int rating)
    {
        update(imageName, location, keywords, imageDate, share, email, rating);
    }

    //A constructor for when we havent assigned any metadata.
    public SwinImage(String imageName)
    {
    }

    public void update(String imageName, String location, String[] keywords, String imageDate, boolean share, String email, int rating)
    {
    }

    @Override
    public String toString()
    {
    }

    private void storeImageDetails() {
    }

    @Override
    //We don't need it - but we are forced to due to interface.
    public int describeContents()
    {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags)
    {
        out.writeString(imageName);
        out.writeString(location);

        out.writeStringArray(keywords);

        out.writeString(imageDate);

        //Can write boolean array but not boolean...
        boolean[] temp = {share};

        out.writeBooleanArray(temp);
        out.writeString(email);

        out.writeInt(rating);
    }

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

        @Override
        public SwinImage createFromParcel(Parcel parcel)
        {
            return new SwinImage(parcel);
        }

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

    //THE PRIVATE CONSTRUCTOR - FOR INTERNAL USE ONLY.
    private SwinImage(Parcel parcel)
    {
        imageName = parcel.readString();
        location = parcel.readString();

        parcel.readStringArray(keywords);

        imageDate = parcel.readString();

        boolean[] tempArr = new boolean[1];
        parcel.readBooleanArray(tempArr);
        share = tempArr[0];

        email = parcel.readString();
        rating = parcel.readInt();
    }

}

好吧。。。所以,在呼叫课上,我会这样做:

public void ClickedImage(View v)
{
    Intent i = new Intent(this, MetaDataActivity.class);

    switch (getResources().getResourceEntryName(v.getId()))
    {
        case "burgerView":
            i.putExtra("SENT_IMAGE", burger); //IT IMPLEMENTS PARCLEABLE THEREFORE WE CAN PASS IT WHERE IT LOOKS FOR A PARCEL
            break;
        case "pitaView":
            i.putExtra("SENT_IMAGE", pita);
            break;
        case "pizzaView":
            i.putExtra("SENT_IMAGE", pizza);
            break;
        case "steakView":
            i.putExtra("SENT_IMAGE", steak);
            break;
    }

    startActivityForResult(i, GET_AND_SET_METADATA_REQUEST);
}

我在最后设置了一个断点,并且确实可以看到它正确地符合意图:

The Intent showing an Extra

然而,当谈到获得它时:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    Log.d("Does", "Does this work");

    Intent i;
    i = getIntent();
    image = i.getExtras().getParcelable("SENT_IMAGE");

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meta_data);
}

它从来就不存在。对image的赋值会使程序崩溃,我甚至无法通过调试器看到我的SwinImage存在于意图中

我做错了什么?为什么会崩溃?我已经尝试了几个小时的解决方案(主要是改变我分配的方式——一些“解决方案”阻止了它崩溃,但是image被分配为空)

有人能提供一些见解吗?谢谢

编辑:

我试图将getIntent移动到onCreate之后,但没有成功

编辑#2:堆栈跟踪:

http://pastebin.com/raw/XJbPxHRv

以及steak等的类型:

public class MainActivity extends AppCompatActivity {

    static final int GET_AND_SET_METADATA_REQUEST = 1;  // The request code
    SwinImage burger, pita, pizza, steak;

共 (2) 个答案

  1. # 1 楼答案

    在以Parcel为参数的SwinImage构造函数中,可以执行以下操作:

    parcel.readStringArray(keywords);
    

    这会失败,因为它试图将String数组读入keywords,这是null,因为您没有首先初始化它

    调用readStringArray()时,向它传递一个对现有String数组的引用,它将把Parcel中的String数组复制到该数组中

    注意readStringArray()writeStringArray()只有在传递给writeStringArray()的数组引用不是null并且传递给readStringArray()的数组中的元素数与传递给writeStringArray()的数组中的元素数完全相同的情况下才能正常工作

    readStringArray()相反,您可能应该使用createStringArray(),它没有这些限制。这样使用:

    keywords = parcel.createStringArray();
    
  2. # 2 楼答案

    你不能在super.onCreate()之前调用getIntent()——此时没有可用的意图

    super呼叫移动到getIntent呼叫之前

    更新:

    在上述修复之后,堆栈跟踪显示问题:

    NullPointerException: Attempt to get length of null array
    at android.os.Parcel.readStringArray(Parcel.java:1026)
    at com.example.kevin.imagemetadata.SwinImage.<init>(SwinImage.java:108)
    

    看起来keywordsnull,所以试图从包裹中读取它会崩溃。 要么确保keywords永远不为空,要么输入一个布尔值,表示是否可以读取关键字。 此外,根据这个:How to use writeStringArray() and readStringArray() in a Parcel您可能应该使用createStringArray而不是readStringArray,这要简单得多

    一般注意事项:您应该始终仔细阅读崩溃堆栈跟踪,以便更好地理解代码没有按预期工作的原因,通常这是修复损坏代码的最佳方法