2016-09-25 59 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();