Android passing an arraylist back to parent activity - java

I've been searching for a simple example of this with no luck.
In my android application I have two activities:
1. The main activity which is launched at startup
2. A second activity which is launched by pressing a button on the main activty.
When the second activity is finished (by pressing a button) I want it to send back an ArrayList of type MyObject to the main activity and close itself, which the main activity can then do whatever with it. How would I go about achieving this? I have been trying a few things but it is crashing my application when I start the second activity.
When the user presses button to launch second activity:
Intent i = new Intent(MainActivity.this, secondactivity.class);
startActivityForResult(i, 1);
The array which is bundled back after pressing a button on the second activity:
Intent intent= getIntent();
Bundle b = new Bundle();
b.putParcelableArrayList("myarraylist", mylist);
intent.putExtras(b);
setResult(RESULT_OK, intent);
finish();
And finally a listener on the main activity (although I'm not sure of 100% when this code launches...)
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK && requestCode==1){
Bundle extras = data.getExtras();
final ArrayList<MyObject> mylist = extras.getParcelableArrayList("myarraylist");
Toast.makeText(MainActivity.this, mylist.get(0).getName(), Toast.LENGTH_SHORT).show();
}
}
Any ideas where I am going wrong? The onActivityResult() seems to be crashing my application.
EDIT: Class with parcelable methods:
import android.os.Parcel;
import android.os.Parcelable;
public class Plan implements Parcelable{
private String name;
private String id;
public Plan(){
}
public Plan createFromParcel(Parcel in) {
Plan plan = new Plan();
plan.setId(in.readString());
plan.setName(in.readString());
return plan;
}
public Plan(String name, String id){
this.name = name;
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
public String toString(){
return "Plan ID: " + id + " Plan Name: " + name;
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(name);
}
public static final Parcelable.Creator<Plan> CREATOR
= new Parcelable.Creator<Plan>() {
public Plan createFromParcel(Parcel in) {
return new Plan();
}
#Override
public Plan[] newArray(int size) {
// TODO Auto-generated method stub
return new Plan[size];
}
};
}
After the second activity finished, onactivityresult is called, but nothing displays inside the toast, its blank. any ideas? I'm guessing my class is still messed up...
EDIT: got it to work
I had the method that Peter supplied in the wrong place. It should be inside creator, like this:
public static final Parcelable.Creator<Plan> CREATOR
= new Parcelable.Creator<Plan>() {
public Plan createFromParcel(Parcel in) {
Plan plan = new Plan();
plan.setId(in.readString());
plan.setName(in.readString());
return plan;
}
and not out on its own.
Many thanks to Peter! Hope this helps someone else.

Your class MyObject must implement Parcelable in order to be serialized/deserialized by Android when put inside Bundle.
Update:
The method name is createFromParcel. And actually you have to create your object Plan from data in the parcel:
public Plan createFromParcel(Parcel in) {
Plan plan = new Plan();
plan.setId(in.readString());
plan.setName(in.readString());
return plan;
}

Related

How to pass data between activity using parcelable in android studio

i have a recyclerview shows the list of movie,
i want when the item movie clicked can pass data to detail using parcelable
this my viewHolderAdapter
public class MovieVHolder extends RecyclerView.ViewHolder {
TextView mTxtTitleMovie, mTxtDescriptionMovie, mTxtDateMovie;
ImageView mImgPosterMovie;
public MovieVHolder(#NonNull final View itemView) {
super(itemView);
mTxtTitleMovie = itemView.findViewById(R.id.txt_title_movie);
mTxtDescriptionMovie = itemView.findViewById(R.id.txt_desc_movie);
mTxtDateMovie = itemView.findViewById(R.id.txt_date_movie);
mImgPosterMovie = itemView.findViewById(R.id.img_movie);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(context, DetailActivity.class);
context.startActivity(i);
}
});
}
public void bind(ListMovieEntity listMovieEntity) {
mTxtTitleMovie.setText(listMovieEntity.getMovieTittle());
mTxtDescriptionMovie.setText(listMovieEntity.getMovieDescription());
mTxtDateMovie.setText(listMovieEntity.getMovieDate());
Glide.with(context)
.load("https://image.tmdb.org/t/p/w185/"+listMovieEntity.getMoviePosterPath())
.into(mImgPosterMovie);
}
}
and I've added parcelable in model class
change itemviewclick like this
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(context, DetailActivity.class);
//addthis i.putExtra(DetailActivity.MOVIE, entListMovie.get(getPosition()));
context.startActivity(i);
}
});
and in the detail make like this
add this
public static final String MOVIE = "movie";
in method onCreate() add this
YourList yourList = getIntent().getParcelableExtra(MOVIE);
after that, just set the data
textview.setText(yourList.getBlaBla());
Intent supports three ways to pass data:
Direct: put our data into intents directly
Bundle: create a bundle and set the data here
Parcelable: It is a way of “serializing” our object.
Passing data: Direct
Intent i = new Intent(context, DetailActivity.class);
i.putExtra("title", mTxtTitleMovie.getText().toString();
i.putExtra("surname", edtSurname.getText().toString();
i.putExtra("email", edtEmail.getText().toString();
context.startActivity(i);
Bundle
Intent i = new Intent(context, DetailActivity.class);
Bundle b = new Bundle();
b.putString("name", edtName.getText().toString());
b.putString("surname", edtSurname.getText().toString());
b.putString("email", edtEmail.getText().toString());
i.putExtra("personBdl", b);
context.startActivity(i);
Passing data: Parcelable
Let’s suppose we have a class called Person that contains three attributes:name, surname and email.
Now if we want to pass this class it must implement the Parcelable interface like that
public class Person implements Parcelable {
private String name;
private String surname;
private String email;
// Get and Set methods
#Override
public int describeContents() {
return hashCode();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeString(email);
}
// We reconstruct the object reading from the Parcel data
public Person(Parcel p) {
name = p.readString();
surname = p.readString();
email = p.readString();
}
public Person() {}
// We need to add a Creator
public static final Parcelable.Creator<person> CREATOR = new Parcelable.Creator<person>() {
#Override
public Person createFromParcel(Parcel parcel) {
return new Person(parcel);
}
#Override
public Person[] newArray(int size) {
return new Person[size];
}
};
Now we simply pass data like that:
Intent i = new Intent(EditActivity.this, ViewActivity.class);
Person p = new Person();
p.setName(edtName.getText().toString());
p.setSurname(edtSurname.getText().toString());
p.setEmail(edtEmail.getText().toString());
i.putExtra("myPers", p);
startActivity(i);
As you notice we simply put our object Person into the Intent. When we receive the data we have:
Bundle b = i.getExtras();
Person p = (Person) b.getParcelable("myPers");
String name = p.getName();
String surname = p.getSurname();
String email = p.getEmail();

Parcelable list inside Parcelable class not reading back with Parcel.readTypedList

I have two Activities, A and B. I am trying to send object from Activity A, to Activity B. When in Activity A, I can see that my List contains two items, but when I retrieve it in Activity B, the List contains 7000000+ records.
Here is my Assessment class, that implements Parcelable, and contains an ArrayList<Photo> which should be parcelable as well.
Assessment POJO:
public class Assessment extends BaseObservable implements Parcelable {
public Assessment(){
}
#SerializedName("Vehicle")
private String vehicle;
#SerializedName("Photos")
private List<Photo> photos;
#Bindable
public String getVehicle() {
return vehicle;
}
public void setVehicle(String vehicle) {
this.vehicle = vehicle;
notifyPropertyChanged(BR.vehicle);
}
public List<Photo> getPhotos() {
return photos;
}
public void setPhotos(List<Photo> photos) {
this.photos = photos;
}
protected Assessment(Parcel in) {
vehicle = in.readString();
photos = new ArrayList<Photo>();
in.readTypedList(photos, Photo.CREATOR);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(vehicle);
dest.writeTypedList(photos);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Assessment> CREATOR = new Parcelable.Creator<Assessment>() {
#Override
public Assessment createFromParcel(Parcel in) {
return new Assessment(in);
}
#Override
public Assessment[] newArray(int size) {
return new Assessment[size];
}
};
}
Photo POJO:
public class Photo implements Parcelable {
public Photo(){
}
#SerializedName("PhotoPath")
private String photoPath;
public String getPhotoPath() {
return photoPath;
}
public void setPhotoPath(String photoPath) {
this.photoPath = photoPath;
}
#SerializedName("Base64PhotoString")
private String photoBase64String;
public String getPhotoBase64String() {
return photoBase64String;
}
public void setPhotoBase64String(String photoBase64String) {
this.photoBase64String = photoBase64String;
}
protected Photo(Parcel in) {
photoPath = in.readString();
photoBase64String = in.readString();
}
//region parelable
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(photoPath);
dest.writeString(photoBase64String);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Photo> CREATOR = new Parcelable.Creator<Photo>() {
#Override
public Photo createFromParcel(Parcel in) {
return new Photo(in);
}
#Override
public Photo[] newArray(int size) {
return new Photo[size];
}
};
//endregion
}
Here is how I send the object via Intent from Activity A, to Activity B:
public void OnAdapterItemClicked(View view){
Intent activityIntent = new Intent(this, com.example.andrewkp.gaassessing.DisplayAssessment.class);
Assessment extraAssessment = getAssessmentFromCollection(view); //extraAssessment.getPhotos().size() == 2
activityIntent.putExtra("assessment", extraAssessment);
startActivity(activityIntent);
}
And here is how I read the Parcelable object in Activity B:
assessment = getIntent().getExtras().getParcelable("assessment");
I have looked at the following article, and I follow exactly what they do, but my photos list does not persist through to Activity B:
When I debug the readTypedList method in Parcel class, I can see that it adds 7000000+ records to my ArrayList, but never removes them. Why is this behavior happening?
You are able to put up to 1MB of data in a Bundle encapsulated inside Intent.
You will get bunch of errors when sending PhotoBase64String in Bundle.
However, in order to overcome this issue, I would suggest path/URI of your photo to your second activity. Then in your second activity, read photo from that path, and perform your desired operation.

How can I get Intent of my custom object in array?

Here's what inside Player.class
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by pietsteph on 15/09/17.
*/
public class Player implements Parcelable{
String name;
int score;
protected Player(Parcel in) {
name = in.readString();
score = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(score);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<Player> CREATOR = new Creator<Player>() {
#Override
public Player createFromParcel(Parcel in) {
return new Player(in);
}
#Override
public Player[] newArray(int size) {
return new Player[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public Player(String name) {
this.name = name;
this.score = 0;
}
}
In the MainActivity.class, I make my custom object as an array with size = 2 (2 player) and put it in intent.
Player players[] = new Player[2];
players[0] = new Player(name1);
players[1] = new Player(name2);
Intent intent = new Intent(getApplicationContext(), TurnActivity.class);
intent.putExtra(PLAYER_KEY, players);
startActivity(intent);
Want to get my intent in TurnActivity.class, tried getParcelableExtra.
Intent intent = getIntent();
Player players[] = intent.getParcelableExtra(MainActivity.PLAYER_KEY);
But it gave me an error
Error:(28, 59) error: incompatible types: inferred type does not conform to upper bound(s)inferred: INT#1
upper bound(s): Player[],Parcelable
where INT#1 is an intersection type:
INT#1 extends Player[],Parcelable
Even tried getParcelableArrayExtra and gave me a red line says Incompatible type.
This is a problem with Java 8. You probably need to do something like this:
Intent intent = getIntent();
Parcelable parcelable[] = intent.getParcelableArrayExtra(MainActivity.PLAYER_KEY);
Now, when you use it, you need to cast it to its proper type. Something like this:
Player player = (Player)parcelable[0];
Implements
Parcalable
interface with
Player
class
I used
Android Parcelable code generator plugin
to do this task.
then you will be able to save your custom objects array in intents.
I use to do something like this
public void moveToNext(ArrayList images){
Intent mainIntent = new Intent(SplashScreen.this,MainActivity.class);
//add data to parcalable
mainIntent.putParcelableArrayListExtra("data",images);
startActivity(mainIntent);
finish();
}
//while getting data
ArrayList v =
getIntent().getParcelableArrayListExtra("data");

NullPointerException on Android Parcelable Object on Intent

I have this problem with this piece of code and I have been a few days trying to solve it and I can't find the solution.
I have this parcelable class:
public class Sistema implements Parcelable{
private ArrayList<Lista> listas;
private ArrayList<Articulo> articulos;
public Sistema() {
listas = new ArrayList<Lista>();
articulos = new ArrayList<Articulo>();
}
public ArrayList<Lista> getListas() {
return listas;
}
public void agregarLista(Lista lista) {
this.getListas().add(lista);
}
public ArrayList<Articulo> getArticulos(){
return this.articulos;
}
public void agregarArticulo(Articulo articulo){
this.getArticulos().add(articulo);
}
public static final Parcelable.Creator<Sistema> CREATOR =
new Parcelable.Creator<Sistema>() {
#Override
public Sistema createFromParcel(Parcel parcel) {
return new Sistema(parcel);
}
#Override
public Sistema[] newArray(int size) {
return new Sistema[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedList(listas);
parcel.writeTypedList(articulos);
}
public Sistema(Parcel parcel)
{
parcel.readTypedList(listas, Lista.CREATOR);
parcel.readTypedList(articulos, Articulo.CREATOR);
}
}
And then in the main i use an intent to send a Sistema object to an other activity:
public void addArticle(View view) {
Intent intent = new Intent(this, AgregarArticulo.class);
intent.putExtra("objectSystem", s);
this.startActivityForResult(intent, 1);
}
Here is where the problem is, i recieve the intent in the second activity with this code:
Intent intento = getIntent();
s = intento.getParcelableExtra("objectSystem");
When I run the code, i get a NullPointerException in the getParcelableExtra
Do you guys have an idea of what the problem should be?
Thanks
Could you please try this . You need to prefix your package name(com.example.whatever) with the name your passing in putExtra:
public void addArticle(View view) {
Intent intent = new Intent(this, AgregarArticulo.class);
intent.putExtra("YOURPACKAGENAME.objectSystem", s);
this.startActivityForResult(intent, 1);
}
and same in getParcelableExtra also:
Intent intento = getIntent();
s = intento.getParcelableExtra("YOURPACKAGENAME.objectSystem");

How can data not stored in a DB be accessed from any activity in Android?

I'm passing data to a ListView to display some restaurant names. Now when clicking on an item I'd like to start another activity to display more restaurant data. I'm not sure about how to do it. Shall I pass all the restaurant data in a bundle through the intent object? Or shall I just pass the restaurant id and get the data in the other activity? In that case, how can I access my restaurantList from the other activity? In any case, how can I get data from the restaurant I clicked on (the view only contains the name)?
Any help, pointers welcome!
ListView lv= (ListView)findViewById(R.id.listview);
lv.setAdapter( new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,restaurantList.getRestaurantNames()));
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(Atable.this, RestaurantEdit.class);
Bundle b = new Bundle();
//b.putInt("id", ? );
startActivityForResult(i, ACTIVITY_EDIT);
}
});
RestaurantList.java
package org.digitalfarm.atable;
import java.util.ArrayList;
import java.util.List;
public class RestaurantList {
private List<Restaurant> restaurants = new ArrayList<Restaurant>();
public List<Restaurant> getRestaurants() {
return this.restaurants;
}
public void setRestaurants(List<Restaurant> restaurants) {
this.restaurants = restaurants;
}
public List<String> getRestaurantNames() {
List<String> restaurantNames = new ArrayList<String>();
for (int i=0; i<this.restaurants.size(); i++) {
restaurantNames.add(this.restaurants.get(i).getName());
}
return restaurantNames;
}
}
Restaurant.java
package org.digitalfarm.atable;
public class Restaurant {
private int id;
private String name;
private float latitude;
private float longitude;
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public float getLatitude() {
return this.latitude;
}
public void setLatitude(float latitude) {
this.latitude = latitude;
}
public float getLongitude() {
return this.longitude;
}
public void setLongitude(float longitude) {
this.longitude = longitude;
}
}
You can not access data from other activities. If you need data in the activity that is started through clicking on the item in the list pass it to the new activity through the message bundle.
If you pass only the id to the next activity you could reload the restaurant from a database or from the internet but you can not retrieve it from the list used in the first activity.
If the restaurants are heavy to create objects you could implement you own application subclass and attach the restaurant list to this application subclass. Now you can access the list like this:
shopList = (YourSubclass)getApplication().getRestaurantList()
This would result in your shoplist being in the memory the wohl runtime of you application even if the app is in the background and all activities are paused.

Categories