2016-09-25 56 views
0

我正在尝试实施Parcleable,以便我可以将其添加为额外的(这是一项要求)。启动活动后没有出现可修复的问题

这里是类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(); 
    } 

} 

好......所以,在调用的类,我这样做:

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被分配了空值)

任何人都可以提供一些见解吗?谢谢。

编辑:

我试图移动getIntentonCreate后无果。

编辑#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; 
+0

如果你有崩溃,为什么不从设备的logcat附加崩溃日志?同时显示代码使用的变量类型('image','pizza'等)。 – Sergio

+0

嗨,谢谢@Serhio我已经更新了OP。 – Kevin

回答

-1

getIntent()之前super.onCreate()不能调用 - 没有意图可在这一点上。

在拨打getIntent之前拨打super电话。

UPDATE:

上面的修复程序后,您的堆栈跟踪显示问题:

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永远不为null,要么放置一个布尔值,表示是否可以读取关键字。 另外,根据这个:How to use writeStringArray() and readStringArray() in a Parcel你应该使用createStringArray而不是readStringArray,这很简单。

一般说明:您应该仔细阅读您的崩溃堆栈痕迹,以便更好地理解为什么代码不能按预期工作,通常这是修复损坏代码的最佳方法。

+0

这是不正确的。 'getIntent()'在'super.onCreate()'之前是有效的。 'Activity'的意图在分派'onCreate()'回调之前被初始化。通常它是通过Activity.attach()完成的。有关详细信息,请参见[https://android.googlesource.com/platform/frameworks/base/+/0e2d281/core/java/android/app/ActivityThread.java#2159]。 – Sergio

+0

嗨,我把它移动到'super.onCreate()'之后,它仍然崩溃:( – Kevin

+0

发布你的堆栈跟踪,无论是intent还是getExtras都为null。 – marmor

0

在你SwinImage构造函数,一个Parcel作为参数,你这样做:

parcel.readStringArray(keywords); 

这失败,因为它试图读取的String一个数组keywords,这是null因为你没有先初始化它。

当您拨打readStringArray()时,您将它传递给现有的String数组,它将从Parcel中复制String的数组。

注意readStringArray()writeStringArray()才会正常工作,如果你传递给writeStringArray()数组引用不是null,如果你传递给readStringArray()数组中元素的数量是完全一样的,你必须元素的数量在阵列中,您传递给writeStringArray()

而不是readStringArray()你应该使用createStringArray()这没有这些限制。像这样使用它:

keywords = parcel.createStringArray();