2016-09-25 1 views
0

Я пытаюсь реализовать Parcleable, чтобы добавить его в качестве дополнительного (это требование).Parcleable extra not there after start activity

Вот похудели версию класса 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 присваивается значение null)

Может ли кто-нибудь дать представление? Благодарю.

Edit:

Я попытался перемещение getIntent к после onCreate безрезультатно.

Edit # 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

Если у вас есть сбой, почему бы не приложить аварийный журнал из ловушки устройства? Также показывайте типы переменных, которые использует ваш код ('image',' pizza' и т. Д.). – Sergio

+0

Привет, спасибо @Serhio Я обновил OP. – Kevin

ответ

-1

Вы не можете позвонить getIntent() перед тем super.onCreate() - не Намерение доступен в этой точке.

Переведите свой super звонок до звонка getIntent.

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) 

keywords кажется это null, поэтому попытка прочитать его от сбоев посылок. Либо убедитесь, что 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

опубликуйте трассировку стека, либо намерение, либо getExtras равны нулю. – marmor

0

В вашем SwinImage конструктор, который принимает Parcel в качестве аргумента, вы делаете это:

parcel.readStringArray(keywords); 

Это терпит неудачу, потому что он пытается прочитать массив String в keywords, который null, потому что вы не инициализировать его первым ,

Когда вы звоните readStringArray(), вы передаете ему ссылку на существующий массив String, в котором он будет копировать массив String из Parcel.

Обратите внимание на readStringArray() и writeStringArray() будет работать правильно, если ссылка на массив, который вы передаете writeStringArray() не null и если число элементов в массиве вы передаете readStringArray() точно так же, как число элементов, которые у вас есть в массиве вы переходите на writeStringArray().

Вместо readStringArray() вы, вероятно, должны использовать createStringArray(), у которого нет этих ограничений. Используйте его следующим образом:

keywords = parcel.createStringArray();