Android: getParcelable returning null? - java

As a follow on from my last question: Passing Arraylist between activities? Using Parcelable
I'm now attempting to pass my ArrayList via Parcelable. However, when it's gotten from the other activity it returns null. I can't seem to figure out why. I've got the following...
ResultsList.java
public class ResultsList extends ArrayList<SearchList> implements Parcelable {
/**
*
*/
private static final long serialVersionUID = -78190146280643L;
public ResultsList(){
}
public ResultsList(Parcel in){
readFromParcel(in);
}
#SuppressWarnings({ "rawtypes" })
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ResultsList createFromParcel(Parcel in) {
return new ResultsList(in);
}
public Object[] newArray(int arg0) {
return null;
}
};
private void readFromParcel(Parcel in) {
this.clear();
//First we have to read the list size
int size = in.readInt();
//Reading remember that we wrote first the Name and later the Phone Number.
//Order is fundamental
for (int i = 0; i < size; i++) {
String title = in.readString();
String Des = in.readString();
String message = in.readString();
SearchList c = new SearchList(title,Des,link);
this.add(c);
}
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
int size = this.size();
//We have to write the list size, we need him recreating the list
dest.writeInt(size);
//We decided arbitrarily to write first the Name and later the Phone Number.
for (int i = 0; i < size; i++) {
SearchList c = this.get(i);
dest.writeString(c.gettitle());
dest.writeString(c.getDescription());
dest.writeString(c.getmessage());
}
}
}
SearchList.java
public class SearchList {
private String title;
private String description;
private String message;
public SearchList(String name, String phone, String mail) {
super();
this.title = name;
this.description = phone;
this.message = mail;
}
public String gettitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getmessage() {
return message;
}
public void setmessage(String link) {
this.message = message;
}
}
listOfResults is declared as ResultsList listOfResults = new ResultsList(); and filled earlier in the code It's then sent with...
Intent intent = new Intent(this ,newthing.class);
Bundle b = new Bundle();
b.putParcelable("results", listOfResults);
startActivityForResult(intent,0);
Receiving...
Bundle extras = getIntent().getExtras();
ResultsList results = extras.getParcelable("results");
I'd like to point out I'm testing this null thing by checking the size() of the Arraylist going into the Bundle and then it coming out. It goes in fine and comes out null.

Didn't attach bundle to intent! (doh!) was pointed out by a kind gent on IRC! #android-dev

Related

How do i pass objects from 1 class to another?

I have 3 classes: MainActivity, homePage and createPage; and a list List<Recipe> recipeList = new ArrayList<>() in MainActivity.
The user enters the homePage from the MainActivity. From homePage, the user can enter createPage and create a new recipe. This new recipe is intended to be passed back to MainActivity.
I've searched online and came across parcels. But when I tried, I get a NullPointerException.
Code for createPage where the list is passed on
ArrayList<Recipe> rList = new ArrayList<>();
Recipe r = new Recipe(...);
rList.add(r)
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelableArrayList("recipe", (ArrayList<? extends Parcelable>) rList);
i.putExtras(b);
i.setClass(createPage.this, homePage.class);
startActivity(i);
Code for homePage where the list is received.
Is there something wrong with the getIntent()? Because when moving from MainActivity to homePage, it doesn't receive a bundle. Is this causing the error?
Intent intent = getIntent();
Bundle b = this.getIntent().getExtras();
if (b != null) {
Recipe r = b.getParcelable("recipe");
recipeList.add(r);
}
Code for Recipe class
public class Recipe implements Parcelable {
private String name;
private String description;
private String ingredients;
private int duration;
private String steps;
private int thumbnail;
protected Recipe(Parcel in) {
name = in.readString();
description = in.readString();
ingredients = in.readString();
duration = in.readInt();
steps = in.readString();
thumbnail = in.readInt();
}
public static final Creator<Recipe> CREATOR = new Creator<Recipe>() {
#Override
public Recipe createFromParcel(Parcel in) {
return new Recipe(in);
}
#Override
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIngredients() {
return ingredients;
}
public void setIngredients(String ingredients) {
this.ingredients = ingredients;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getSteps() { return steps; }
public void setSteps(String steps) { this.steps = steps; }
public int getThumbnail() { return thumbnail; }
public Recipe() {}
public Recipe(String name, int duration, String ingredients, String description, String steps, int thumbnail) {
this.name = name;
this.description = description;
this.ingredients = ingredients;
this.duration = duration;
this.steps = steps;
this.thumbnail = thumbnail;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(description);
parcel.writeString(ingredients);
parcel.writeInt(duration);
parcel.writeString(steps);
parcel.writeInt(thumbnail);
}
}
you are writing into Parcelable whole array under "recipe" key
b.putParcelableArrayList("recipe", (ArrayList<? extends Parcelable>) rList);
but on onther side you are looking not for list but for single Recipe item under same key
Recipe r = b.getParcelable("recipe");
you should use getParcelableArrayList or if you have only one Recipe for passing to another Activity just use putParcelable (not list)
Alternatively you can use serializable, that will be less complex.
For reference : https://stackoverflow.com/a/2736612/9502601
Eventhough parcellables are more faster but if you want a less complex solution then you can go for it.
For Comparison between Serializable and Parcelable.
https://stackoverflow.com/a/23647471/9502601
You can use this gson Lib for this
implementation 'com.google.code.gson:gson:2.8.9'
Send Data with Intent
Recipe r = new Recipe(...);
String recipeString = new Gson().toJson(r);
intent.putExtra("recipe",recipeString);
// For ArrayList
ArrayList<Recipe> recipeList = new ArrayList<>();
String recipeString = new Gson().toJson(recipeList);
intent.putExtra("recipeList",recipeString);
Receive Data From Intent
Recipe r = new Gson().fromJson(intent.getStringExtra("recipe"), Recipe.class);
// For Array List
Type listType = new TypeToken<ArrayList<Recipe>>(){}.getType();
ArrayList<Recipe> recipeList = new Gson().fromJson(intent.getStringExtra("recipeList"),listType);

Can't solve "Parcelable encountered IOException writing serializable object"

java.lang.RuntimeException: Parcelable encountered IOException writing
serializable object (name = com.luzian.recipeapp.Recipe)
I've already searched for answers for this problem but they all seem to be fixed by letting both classes implement from Serializable - which I'm doing - without success.
My two Classes Recipe and Ingredient:
public class Recipe implements Serializable
{
private String name;
private String time;
private String instructions;
private ArrayList<Ingredient> ingredients;
public Recipe(String name, String time, String instructions, ArrayList<Ingredient> ingredients)
{
this.name = name;
this.time = time;
this.instructions = instructions;
this.ingredients = ingredients;
}
}
public class Ingredient implements Serializable
{
private String value;
private String unit;
private String name;
public Ingredient(String value, String unit, String name)
{
this.value = value;
this.unit = unit;
this.name = name;
}
}
Starting new Activity:
Intent intent = new Intent(context, RecipeDisplayActivity.class);
intent.putExtra("recipe", recipes.get(position)); // recipes.get(position) returns a Recipe object
context.startActivity(intent);
I changed the Serializable to Parcelable and overwrote to required methods - Now it works!
Thanks #Swayangjit
public class Recipe implements Parcelable
{
private String name;
private String time;
private String instructions;
private ArrayList<Ingredient> ingredients;
public Recipe(String name, String time, String instructions, ArrayList<Ingredient> ingredients)
{
this.name = name;
this.time = time;
this.instructions = instructions;
this.ingredients = ingredients;
}
protected Recipe(Parcel in)
{
name = in.readString();
time = in.readString();
instructions = in.readString();
ingredients = in.readArrayList(Ingredient.class.getClassLoader());
}
public static final Creator<Recipe> CREATOR = new Creator<Recipe>()
{
#Override
public Recipe createFromParcel(Parcel in)
{
return new Recipe(in);
}
#Override
public Recipe[] newArray(int size)
{
return new Recipe[size];
}
};
#Override
public int describeContents()
{
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeString(name);
dest.writeString(time);
dest.writeString(instructions);
dest.writeList(ingredients);
}
}
public class Ingredient implements Parcelable
{
private String value;
private String unit;
private String name;
public Ingredient(String value, String unit, String name)
{
this.value = value;
this.unit = unit;
this.name = name;
}
protected Ingredient(Parcel in)
{
value = in.readString();
unit = in.readString();
name = in.readString();
}
public static final Creator<Ingredient> CREATOR = new Creator<Ingredient>()
{
#Override
public Ingredient createFromParcel(Parcel in)
{
return new Ingredient(in);
}
#Override
public Ingredient[] newArray(int size)
{
return new Ingredient[size];
}
};
#Override
public int describeContents()
{
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeString(value);
dest.writeString(unit);
dest.writeString(name);
}
}

Android - How to send and receive nested parceled objects "Bundles"

I am trying to send and receive a parceled array object within another parceled object through bundles.
Always, Having issues with Array lengths
CODE : PARCELED ARRAY OBJECTS Author.java
public class Author implements Parcelable {
public String firstName;
public String middleInitial;
public String lastName;
public Author() {
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(this.firstName);
out.writeString(this.middleInitial);
out.writeString(this.lastName);
}
private Author(Parcel in) {
this.firstName = in.readString();
this.middleInitial = in.readString();
this.lastName = in.readString();
}
public int describeContents(){
return 0;
}
public static final Parcelable.Creator<Author> CREATOR = new Parcelable.Creator<Author>() {
#Override
public Author createFromParcel(Parcel in) {
return new Author(in);
}
#Override
public Author[] newArray(int size) {
return new Author[size];
}
};
public String toString() {
StringBuffer sb = new StringBuffer();
if (firstName != null && !"".equals(firstName)) {
sb.append(firstName);
sb.append(' ');
}
if (middleInitial != null && !"".equals(middleInitial)) {
sb.append(middleInitial);
sb.append(' ');
}
if (lastName != null && !"".equals(lastName)) {
sb.append(lastName);
}
return sb.toString();
}
}
CODE : PARCELED BOOK OBJECT Book.java
public class Book implements Parcelable {
public int id;
public String title;
public Author[] authors;
public String isbn;
public String price;
private Book(Parcel in) {
this.id = in.readInt();
this.title = in.readString();
in.readTypedArray(authors, Author.CREATOR);
this.isbn = in.readString();
this.price = in.readString();
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(this.id);
out.writeString(this.title);
out.writeArray(this.authors);
out.writeString(this.isbn);
out.writeString(this.price);
}
public int describeContents(){
return 0;
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
#Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
#Override
public Book[] newArray(int size) {
return new Book[size];
}
};
public Book(int id, String title, Author[] author, String isbn, String price) {
this.id = id;
this.title = title;
this.authors = author;
this.isbn = isbn;
this.price = price;
}
}
Call and Create objects :
Book new_book = new Book(1, title, authors.parseAuthors(author), isbn, "35$");
Intent i = new Intent(this, BookActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable("key", new_book);
i.putExtras(bundle);
startActivity(i);
Remote Activity "BOOK ACTIVITY.CLASS"
Bundle bundle = getIntent().getExtras();
Book book = bundle.getParcelable("key");
Any ideas, how can i fix this issue.? NESTED PARCELED WITHIN BUNDLES. Also, I am sure if i am using the right way to read array in parcelable on author object.
Thanks,
Try using Parcel.createTypedArray(ClassLoader...) instead. From what I'm seeing, you're using readTypedArray, but not initializing the destination array before trying to read into it. In order to do it that way, you'd need to pass the current length of the array through the Parcel, and initialize the array at the correct size before reading into it.

writing multiple objects to parcel

I am trying to save an enum 'Status' into a custom class that implements parcelable. I have found online how I can save Strings, ints or enums in one class that implements parcelable, but not how I can save these three things all at once. I am sorry if the solution is obvious, but I just can't figure it out.
Here is what my enum looks like:
public enum Status {
INITIALIZED, UPDATED, DELETED
}
And this is what I have so far:
public class Recipe implements Parcelable{
private String id;//this should be an int, same problem
private String recipeName;
private String recipePreperation;
private Status status;
private final static int MAX_PREVIEW = 50;
public Recipe(int parId, String parRecipeName, String parRecipePreperation) {
this.id = "" + parId;
this.recipeName = parRecipeName;
this.recipePreperation = parRecipePreperation;
this.status = Status.INITIALIZED;
}
public Recipe(Parcel in){
String[] data = new String[4];
in.readStringArray(data);
this.id = data [0];
this.recipeName = data[1];
this.recipePreperation = data[2];
this.status = data[3];//what I intend to do, I know this is wrong
}
public int GetId() {
return Integer.parseInt(id);
}
public String GetRecipeName() {
return this.recipeName;
}
public void SetRecipeName(String parRecipeName) {
this.recipeName = parRecipeName;
}
public String GetRecipePreperation() {
return this.recipePreperation;
}
public void SetRecipePreperation(String parRecipePreperation) {
this.recipePreperation = parRecipePreperation;
}
public Status GetStatus() {
return this.status;
}
public void SetStatus(Status parStatus) {
this.status = parStatus;
}
public String toString() {
String recipe = this.recipeName + "\n" + this.recipePreperation;
String returnString;
int maxLength = MAX_PREVIEW;
if (recipe.length() > maxLength) {
returnString = recipe.substring(0, maxLength - 3) + "...";
} else {
returnString = recipe;
}
return returnString;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int arg1) {
dest.writeStringArray(new String [] {
this.id,
this.recipeName,
this.recipePreperation,
this.status//what I intend to do, I know this is wrong
});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Recipe createFromParcel(Parcel in) {
return new Recipe(in);
}
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
}
How do I save an int, an array of strings and an enum into a class that implements the parcelable, so it can writeToParcel()?
There's no need to read and write to/from string array. Just write each string and finally the status as Serializable. This is how I fix it.
public Recipe(Parcel in){
this.id = in.readString();
this.recipeName = in.readString();
this.recipePreperation = in.readString();
this.status = (Status) in.readSerializable();
}
public void writeToParcel(Parcel dest, int arg1) {
dest.writeString(this.id);
dest.writeString(this.recipeName);
dest.writeString(this.recipePreperation);
dest.writeSerializable(this.status);
}

Pass List with custom object to another activity android

I have a List<News> new ArrayList<News>(); I need to pass this list to another activity and retrieve object from it to assign it to String values.
News.java
public class News
{
String title;
String description;
String thumbnail;
String newsUrl;
String body;
String newsBigImage ;
String newsComments ;
String newsViews;
String publishedDate;
String articleGuid;
String newsSourceId;
String newsId ;
String publisherName;
String newsSourceTitle;
String color;
News(String title, String description, String thumbnail, String newsUrl, String body, String newsBigImage, String newsComments, String newsViews,
String publishedDate,
String articleGuid,
String newsSourceId,
String newsId ,
String publisherName,
String newsSourceTitle )
{
this.title = title;
this.description = description;
this.articleGuid =articleGuid;
this.thumbnail = thumbnail;
this.newsUrl = newsUrl;
this.body = body;
this.newsBigImage = newsBigImage;
this.newsComments = newsComments;
this.newsViews = newsViews;
this.publishedDate = publishedDate;
this.newsId = newsId;
this.newsSourceId = newsSourceId;
this.publisherName = publisherName;
//this.color = color;
this.newsSourceTitle =newsSourceTitle;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
public String getNewsUrl() {
return newsUrl;
}
public void setNewsUrl(String newsUrl) {
this.newsUrl = newsUrl;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getNewsBigImage() {
return newsBigImage;
}
public void setNewsBigImage(String newsBigImage) {
this.newsBigImage = newsBigImage;
}
public String getNewsComments() {
return newsComments;
}
public void setNewsComments(String newsComments) {
this.newsComments = newsComments;
}
public String getNewsViews() {
return newsViews;
}
public void setNewsViews(String newsViews) {
this.newsViews = newsViews;
}
public String getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
public String getArticleGuid() {
return articleGuid;
}
public void setArticleGuid(String articleGuid) {
this.articleGuid = articleGuid;
}
public String getNewsSourceId() {
return newsSourceId;
}
public void setNewsSourceId(String newsSourceId) {
this.newsSourceId = newsSourceId;
}
public String getNewsId() {
return newsId;
}
public void setNewsId(String newsId) {
this.newsId = newsId;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getNewsSourceTitle() {
return newsSourceTitle;
}
public void setNewsSourceTitle(String newsSourceTitle) {
this.newsSourceTitle = newsSourceTitle;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
I pass values like:-
myNewsList.add(new News(title, description, thumbnail, newsUrl, body, newsBigImage, newsComments, newsViews, publishedDate, articleGuid, newsSourceId, newsId, publisherName, newsSourceTitle));
Then I pass this list to an ListAdapter to show it in a ListView.
itemsAdapter = new LazyAdapter(myContext, myNewsList);
newsList.setAdapter(itemsAdapter);
Now, When the user clicks a listview item, I want to pass the myNewsList to the new activity and retrieve items from it and assign it to another Strings in that class.
ewsList.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0,
View arg1, int position, long arg3)
{
// TODO Auto-generated method stub
myDialog = new ProgressDialog(myContext).show(getActivity(), "Fetching news..", "Just a moment");
//News myMap = myNewsList.get(position);
Intent newsIntent = new Intent(getActivity(),NewsDetails.class);
startActivity(newsIntent);
How can I do this??
implements a parcelable interface so your class will look like
public class News implements Parcelable {
String title;
String description;
String thumbnail;
String newsUrl;
String body;
String newsBigImage ;
String newsComments ;
String newsViews;
String publishedDate;
String articleGuid;
String newsSourceId;
String newsId ;
String publisherName;
String newsSourceTitle;
String color;
protected News(Parcel in) {
title = in.readString();
description = in.readString();
thumbnail = in.readString();
newsUrl = in.readString();
body = in.readString();
newsBigImage = in.readString();
newsComments = in.readString();
newsViews = in.readString();
publishedDate = in.readString();
articleGuid = in.readString();
newsSourceId = in.readString();
newsId = in.readString();
publisherName = in.readString();
newsSourceTitle = in.readString();
color = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(description);
dest.writeString(thumbnail);
dest.writeString(newsUrl);
dest.writeString(body);
dest.writeString(newsBigImage);
dest.writeString(newsComments);
dest.writeString(newsViews);
dest.writeString(publishedDate);
dest.writeString(articleGuid);
dest.writeString(newsSourceId);
dest.writeString(newsId);
dest.writeString(publisherName);
dest.writeString(newsSourceTitle);
dest.writeString(color);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<News> CREATOR = new Parcelable.Creator<News>() {
#Override
public News createFromParcel(Parcel in) {
return new News(in);
}
#Override
public News[] newArray(int size) {
return new News[size];
}
};
}
and you can pass now this in intent extra like
intent.putExtra("newsObject", obj);
and for passing arraylist do Intent.putParcelableArrayListExtra("newsList", arr);
and in next activity get like
News news = (News)intent.getParcelableExtra("newsObject");
and for getting arraylist do
ArrayList<News> news = (ArrayList<News>)intent.getParcelableArrayListExtra("newsList");
Use Seriazable or Parceable interface implementation for this.
In NewsDetails class just you want to show the description so call getters method of model class and show there, or else follow above solution
first, create a getter method to retreive your object in adapter.. returning your List then you call your getter in your activity, then you create your intent.

Categories

Resources