user3246736
user3246736

Reputation: 51

NullPointerException when passing Parcelable extras

I keep getting a NullPointerException when I try to pass an Intent with a Parcelable extra. I've got two parcalable classes, author.java and Book.java. Author needs to be included in the Book as array of Parcelables. And then the Book object should be passed as extra using Intent.

Here's the code

import android.os.Parcel;
import android.os.Parcelable;

public class Author implements Parcelable{

public String firstName = null;

public String middleInitial = null;

public String lastName = null;

public Author(String[] authorName){
    if(authorName.length == 1){
        this.lastName = authorName[0];
    }else if(authorName.length == 2){
        this.firstName = authorName[0];
        this.lastName = authorName[1];  
    }else if(authorName.length >= 3){
        this.firstName = authorName[0];
        this.middleInitial = authorName[1];
        this.lastName = authorName[2];
    }else if(authorName.length == 0){
        //nothing needs to be done
    }
}

public Author(String firstName, String middleInitial, String lastName){
    this.firstName = firstName;
    this.middleInitial = middleInitial;
    this.lastName = lastName;
}

public Author(Parcel in){
    String[] data = new String[3];

    in.readStringArray(data);
    this.firstName = data[0];
    this.middleInitial = data[1];
    this.lastName = data[2];
}

public static final Parcelable.Creator<Author> CREATOR = new Parcelable.Creator<Author>() {
    public Author createFromParcel(Parcel in) {
        return new Author(in); 
    }
    public Author[] newArray(int size) {
        return new Author[size];
    }
};

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    String[] array = new String[3];
    array[0] = this.firstName;
    array[1] = this.middleInitial;
    array[2] = this.lastName;
    dest.writeStringArray(array);
}

}

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable{

// TODO Modify this to implement the Parcelable interface.

// TODO redefine toString() to display book title and price (why?).

public int id;

public String title;

public String isbn;

public String price;

public Author[] authors;

public Book(int id, String title, Author[] author, String isbn, String price) {
    this.id = id;
    this.title = title;
    this.authors = new Author[author.length];
    for(int i = 0; i < author.length; i++){
        authors[i] = author[i];
    }
    this.isbn = isbn;
    this.price = price;
}

public Book(Parcel in){      
    int intdata = in.readInt();
    this.id = intdata;

    String[] data = new String[3];
    in.readStringArray(data);
    this.title = data[0];
    this.isbn = data[1];
    this.price = data[2];

    Author[] authorsT = (Author[]) in.readParcelableArray(Author.class.getClassLoader());
    this.authors = new Author[authorsT.length];
    for(int i = 0; i < authorsT.length; i++){
        authors[i] = authorsT[i];
    }
}

public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
    public Book createFromParcel(Parcel in) {
        return new Book(in); 
    }
    public Book[] newArray(int size) {
        return new Book[size];
    }
};

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(id);
    String[] data = new String[3];
    data[0] = title;
    data[1] = isbn;
    data[2] = price;
    dest.writeStringArray(data);
    if(authors == null){
        authors = new Author[1];
    }
    dest.writeParcelableArray(authors, flags);

}

@Override
public String toString(){
    return isbn;

}

}

Here's how i send the Intent:

Intent result = new Intent();
        result.putExtra(BOOK_RESULT_KEY, resultBook);
        setResult(RESULT_OK, result);
        finish();

And try to get the extra:

Bundle data = getIntent().getExtras();
Book book = (Book)data.getParcelable(AddBookActivity.BOOK_RESULT_KEY);
String a = book.authors[0].lastName;

Error log indicates that the error happens when i try to access object book:

    01-28 18:10:59.248: W/dalvikvm(1334): threadid=1: thread exiting with uncaught exception (group=0xb1a4cba8)
01-28 18:10:59.248: E/AndroidRuntime(1334): FATAL EXCEPTION: main
01-28 18:10:59.248: E/AndroidRuntime(1334): Process: edu.stevens.cs522, PID: 1334
01-28 18:10:59.248: E/AndroidRuntime(1334): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {edu.stevens.cs522/edu.stevens.cs522.BookStoreActivity}: java.lang.NullPointerException
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.ActivityThread.deliverResults(ActivityThread.java:3365)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.ActivityThread.handleSendResult(ActivityThread.java:3408)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.ActivityThread.access$1300(ActivityThread.java:135)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.os.Handler.dispatchMessage(Handler.java:102)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.os.Looper.loop(Looper.java:136)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.ActivityThread.main(ActivityThread.java:5017)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at java.lang.reflect.Method.invokeNative(Native Method)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at java.lang.reflect.Method.invoke(Method.java:515)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at dalvik.system.NativeStart.main(Native Method)
01-28 18:10:59.248: E/AndroidRuntime(1334): Caused by: java.lang.NullPointerException
01-28 18:10:59.248: E/AndroidRuntime(1334):     at edu.stevens.cs522.BookStoreActivity.onActivityResult(BookStoreActivity.java:101)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.Activity.dispatchActivityResult(Activity.java:5423)
01-28 18:10:59.248: E/AndroidRuntime(1334):     at android.app.ActivityThread.deliverResults(ActivityThread.java:3361)
01-28 18:10:59.248: E/AndroidRuntime(1334):     ... 11 more

Could anyone help me?

UPDATE: Here is how the resultBook is created:

public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);
        // TODO

        // SEARCH: return the book details to the BookStore activity

        // CANCEL: cancel the search request
        switch (item.getItemId()){
        case R.id.search:
            Book resultBook = searchBook();
            Log.e("resulrBook:", resultBook.authors[0].lastName);
            Intent result = new Intent();
            result.putExtra(BOOK_RESULT_KEY, resultBook);
            setResult(RESULT_OK, result);
            finish();
        case R.id.cancel:
            setResult(RESULT_CANCELED, null);
            finish();
        default:
            return
            super.onOptionsItemSelected(item);
        }
    }

    public Book searchBook(){
        /*
         * Search for the specified book.
         */
        // TODO Just build a Book object with the search criteria and return that.
        EditText editAuthor = (EditText) findViewById(R.id.search_author);
        String authorString = editAuthor.getText().toString();
        String[] authors = authorString.split(", ");
        Author[] authorsArray = new Author[authors.length];
        for(int i = 0; i < authors.length; i++){
            authorsArray[i] = new Author(authors[i].split(" "));
        }

        EditText editTitle = (EditText) findViewById(R.id.search_title);
        EditText editIsbn = (EditText) findViewById(R.id.search_isbn);
        String title = editTitle.getText().toString();
        String isbn = editIsbn.getText().toString();

        Log.e(title, authorsArray[0].lastName);
        Log.e("isbn:", isbn);

        Book newBook = new Book(100, title, authorsArray, isbn, "10");
        Log.e("Book author:", newBook.authors[0].lastName);
        return newBook;
    }

}

Upvotes: 2

Views: 2032

Answers (1)

user3246736
user3246736

Reputation: 51

Problem solved...

It's a stupid error...

I was actually trying to get the passed extra in OnActivityResult() function. However, in that function, getIntent() shouldn't be used to fetch the intent returned by the child activity. You should used the intent that is passed as an argument in that function directly:

protected void onActivityResult(int requestCode, int resultCode, Intent intent) 

And write something like this to get the parcelable extra:

Bundle data = intent.getExtra();
Book book = (Book)data.getParcelable(PARCELABLE_NAME);

Hope it helps.

Upvotes: 3

Related Questions