Parcleable extra 启动后不存在 activity
Parcleable extra not there after starting activity
我正在尝试实现 Parcleable,以便我可以将其作为额外添加(这是一项要求)。
这里是 class SwinImage
的精简版,它只显示相关细节,即派生自 Parcleable 的部分:
package com.example.kevin.imagemetadata;
import android.os.Parcel;
import android.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();
}
}
好的...因此,在调用 class 时,我这样做:
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);
}
我在最后打了个断点,确实能看出来是原意对的:
然而,当谈到获得它时:
@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
甚至存在于意图中。
我做错了什么?为什么会崩溃?我已经尝试了几个小时的解决方案(主要是改变了我的分配方式 - 有些 "solutions" 已经阻止它崩溃,但是 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;
您不能在 super.onCreate()
之前调用 getIntent()
- 此时没有可用的 Intent。
将您的 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)
似乎 keywords
是 null
,因此尝试从包裹中读取它时崩溃了。
要么确保 keywords
永远不会为 null,要么放置一个布尔值来说明是否可以读取关键字。
另外,根据这个:How to use writeStringArray() and readStringArray() in a Parcel 你应该使用 createStringArray 而不是 readStringArray,简单得多。
一般注意事项:您应该始终仔细阅读崩溃堆栈跟踪,以更好地理解您的代码为何无法按预期工作,通常这是修复损坏代码的最佳方法。
在以 Parcel
作为参数的 SwinImage
构造函数中,您可以这样做:
parcel.readStringArray(keywords);
这失败了,因为它试图将 String
的数组读入 keywords
,这是 null
,因为你没有先初始化它。
当您调用 readStringArray()
时,您将对 String
的现有数组的引用传递给它,它将从 Parcel
复制 String
的数组到其中.
注意 readStringArray()
和 writeStringArray()
只有在您传递给 writeStringArray()
的数组引用不是 null
并且如果您传递给 readStringArray()
的数组与您传递给 writeStringArray()
.
的数组中的元素数量完全相同
您应该使用没有这些限制的 createStringArray()
而不是 readStringArray()
。像这样使用它:
keywords = parcel.createStringArray();
我正在尝试实现 Parcleable,以便我可以将其作为额外添加(这是一项要求)。
这里是 class SwinImage
的精简版,它只显示相关细节,即派生自 Parcleable 的部分:
package com.example.kevin.imagemetadata;
import android.os.Parcel;
import android.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();
}
}
好的...因此,在调用 class 时,我这样做:
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);
}
我在最后打了个断点,确实能看出来是原意对的:
然而,当谈到获得它时:
@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
甚至存在于意图中。
我做错了什么?为什么会崩溃?我已经尝试了几个小时的解决方案(主要是改变了我的分配方式 - 有些 "solutions" 已经阻止它崩溃,但是 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;
您不能在 super.onCreate()
之前调用 getIntent()
- 此时没有可用的 Intent。
将您的 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)
似乎 keywords
是 null
,因此尝试从包裹中读取它时崩溃了。
要么确保 keywords
永远不会为 null,要么放置一个布尔值来说明是否可以读取关键字。
另外,根据这个:How to use writeStringArray() and readStringArray() in a Parcel 你应该使用 createStringArray 而不是 readStringArray,简单得多。
一般注意事项:您应该始终仔细阅读崩溃堆栈跟踪,以更好地理解您的代码为何无法按预期工作,通常这是修复损坏代码的最佳方法。
在以 Parcel
作为参数的 SwinImage
构造函数中,您可以这样做:
parcel.readStringArray(keywords);
这失败了,因为它试图将 String
的数组读入 keywords
,这是 null
,因为你没有先初始化它。
当您调用 readStringArray()
时,您将对 String
的现有数组的引用传递给它,它将从 Parcel
复制 String
的数组到其中.
注意 readStringArray()
和 writeStringArray()
只有在您传递给 writeStringArray()
的数组引用不是 null
并且如果您传递给 readStringArray()
的数组与您传递给 writeStringArray()
.
您应该使用没有这些限制的 createStringArray()
而不是 readStringArray()
。像这样使用它:
keywords = parcel.createStringArray();