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);
}
我在最后设置了一个断点,并且确实可以看到它正确地符合意图:
然而,当谈到获得它时:
@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;
# 1 楼答案
在以
Parcel
为参数的SwinImage
构造函数中,可以执行以下操作:这会失败,因为它试图将
String
数组读入keywords
,这是null
,因为您没有首先初始化它调用
readStringArray()
时,向它传递一个对现有String
数组的引用,它将把Parcel
中的String
数组复制到该数组中注意
readStringArray()
和writeStringArray()
只有在传递给writeStringArray()
的数组引用不是null
并且传递给readStringArray()
的数组中的元素数与传递给writeStringArray()
的数组中的元素数完全相同的情况下才能正常工作与
readStringArray()
相反,您可能应该使用createStringArray()
,它没有这些限制。这样使用:# 2 楼答案
你不能在
super.onCreate()
之前调用getIntent()
——此时没有可用的意图将
super
呼叫移动到getIntent
呼叫之前更新:
在上述修复之后,堆栈跟踪显示问题:
看起来
keywords
是null
,所以试图从包裹中读取它会崩溃。 要么确保keywords
永远不为空,要么输入一个布尔值,表示是否可以读取关键字。 此外,根据这个:How to use writeStringArray() and readStringArray() in a Parcel您可能应该使用createStringArray而不是readStringArray,这要简单得多一般注意事项:您应该始终仔细阅读崩溃堆栈跟踪,以便更好地理解代码没有按预期工作的原因,通常这是修复损坏代码的最佳方法