How to parcelable class with own objects and enums - android

I have class tariff and i need to parcelable it.
public class Tariff implements Parcelable{
private String operator;
private Discounts discount;
private boolean unlimited;
private Billings billing;
private String name;
private double price;
private double calculated;
private Call call;
private Sms sms;
I found some advices here but im not sure i´m getting them right.
1) For parcelable enum I found this. Will that parcelable all values of my enum? Or how should i do that?
try {
type = Discounts.valueOf(in.readString());
} catch (IllegalArgumentException x) {
type = null;
}
2) For parcelable another object(for example call) i found this: If the CategoryDate class is one of yours, you can make it Parcelable as well. Then in your class' writeToParcel() call you can call this.date.writeToParcel() and pass it the same Parcel object. This will cause the CategoryDate class to write its data into the same Parcel object which is being used by CloseItPending.
But i´m not sure i got it right. How exactly should i do that?

Parcelable it's really a lot of boilerplate that, coding manually, have a great chance to fall in error.
Use this site: http://www.parcelabler.com/
This tool automatic generate the parcelable fields for your class. Remember to make the Classes declared as class variables to be parcelable too.
The result will be somenthing like this:
public class Tariff implements Parcelable {
private String operator;
private Discounts discount;
private boolean unlimited;
private Billings billing;
private String name;
private double price;
private double calculated;
private Call call;
private Sms sms;
protected Tariff(Parcel in) {
operator = in.readString();
discount = (Discounts) in.readValue(Discounts.class.getClassLoader());
unlimited = in.readByte() != 0x00;
billing = (Billings) in.readValue(Billings.class.getClassLoader());
name = in.readString();
price = in.readDouble();
calculated = in.readDouble();
call = (Call) in.readValue(Call.class.getClassLoader());
sms = (Sms) in.readValue(Sms.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(operator);
dest.writeValue(discount);
dest.writeByte((byte) (unlimited ? 0x01 : 0x00));
dest.writeValue(billing);
dest.writeString(name);
dest.writeDouble(price);
dest.writeDouble(calculated);
dest.writeValue(call);
dest.writeValue(sms);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Tariff> CREATOR = new Parcelable.Creator<Tariff>() {
#Override
public Tariff createFromParcel(Parcel in) {
return new Tariff(in);
}
#Override
public Tariff[] newArray(int size) {
return new Tariff[size];
}
};
}

Related

Pass Objects between Activities

I'm devlopping an Android app made of multiple Activities and I have to pass ab Object between them, but I can't pass it by using intents because the class of the object doesn't implement serializable, how can I do it?
I CAN'T MODIFY THE SOURCE CODE OF MY CLASS
Thanks :)
public class MyClass { //stuff }
//I can't modify this source code
MyClass m = new MyClass(); //object I have to pass
Suppose there is a data object class named StudentDataObject having some data types.
StudentDataObject studentDataObject = new StudentDataObject();
Gson gson = new Gson();
String studentDataObjectAsAString = gson.toJson(studentDataObject);
Now we are passing it from one activity to another activity using intent.
Intent intent = new Intent(FromActivity.this, ToActivity.class);
intent.putExtra("MyStudentObjectAsString", studentDataObjectAsAString);
startActivity(intent);
Now we are in new activity, we get that object here using following line.
Gson gson = new Gson();
String studentDataObjectAsAString = getIntent().getStringExtra("MyStudentObjectAsString");
StudentDataObject studentDataObject = gson.fromJson(studentDataObjectAsAString, StudentDataObject.class);
Activity itself know where from I am called, so we can directly write getIntent() method.
Here we only need to add one dependency of GSON we can add it using following line in build.gradle file.
compile 'com.google.code.gson:gson:2.6.2'
And one thing is that implement StudentDataObject as a Parcelable and if showing error then just press alt+Enter and implement methods.
Try this once, Hope it will work.
Sample Example for StudentDataObject should be like :-
public class StudentDataObject implements Parcelable {
// fields
//empty constructor
//parameterised constructor
//getters and setters
//toString method
//last implement some Parcelable methods
}
First of all create Parcelable data model.
public class DataModel implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<DataModel> CREATOR
= new Parcelable.Creator<DataModel>() {
public DataModel createFromParcel(Parcel in) {
return new DataModel(in);
}
public DataModel[] newArray(int size) {
return new DataModel[size];
}
};
private DataModel(Parcel in) {
mData = in.readInt();
}
}
put object into intent
intent.putExtra("KEY", object);
get object from intent
object = getIntent().getExtras().getParcelable("KEY");
This code may help you:
public class EN implements Serializable {
//... you don't need implement any methods when you implements Serializable
}
FirstActivity
EN enumb = new EN();
Intent intent = new Intent(getActivity(), NewActivity.class);
intent.putExtra("en", enumb); //second param is Serializable
startActivity(intent);
SecandActivity
Bundle extras = getIntent().getExtras();
if (extras != null) {
en = (EN)getIntent().getSerializableExtra("en"); //Obtaining data
}
Passing data through intent using Serializable
Here is my object class Book.java
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
// book basics
private String title;
private String author;
// main constructor
public Book(String title, String author) {
this.title = title;
this.author = author;
}
// getters
public String getTitle() { return title; }
public String getAuthor() { return author; }
// write object values to parcel for storage
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(author);
}
public Book(Parcel parcel) {
title = parcel.readString();
author = parcel.readString();
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
#Override
public Book createFromParcel(Parcel parcel) {
return new Book(parcel);
}
#Override
public Book[] newArray(int size) {
return new Book[0];
}
};
public int describeContents() {
return hashCode();
}
}
Now you can pass object like this
Button button = (Button) findViewById(R.id.submit_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Book book = new Book(mBkTitle.getText().toString(),
mBkAuthor.getText().toString());
Intent intent = new Intent(MainActivity.this, BookActivity.class);
intent.putExtra("Book", book);
startActivity(intent);
}
});
Now object will be received like this in receiving ReceivingActivity.java
Intent intent = getIntent();
Book book = intent.getParcelableExtra("Book");
mBkTitle.setText("Title:" + book.getTitle());
mBkAuthor.setText("Author:" + book.getAuthor());
You need to implement parcelable and then pass it via intent. Dont use Serializable cause is way slower than parcelable.
Read here how to make your object parcelable: https://developer.android.com/reference/android/os/Parcelable.html
after you dont it, pass your object like this:
intent.putExtra("KEY", your_object);
to read it:
getIntent().getExtras().getParcelable("KEY");
Extend the class and implement serializable or parcelable in the inherited class and use its objects as in other answers.
Class NewClass extends MyClass implements serializable {
//Create a constructor matching super
}
Use objects of this class instead of my class
You can pass a custom object from one activity to another through intent in 2 ways.
By implements Serializable
By implements Parcelable
(1) By implements Serializable no need to do anything just implement Serializable
into your class like
public class Note implements Serializable {
private int id;
private String title;
}
(2) By implementing Parcelable (you have to follow the Parcel write and read with same order)
public class Note implements Parcelable {
private int id;
private String title;
public Note() {
}
Note(Parcel in){
this.id = in.readInt();
this.title = in.readString();
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(title);
}
public static final Parcelable.Creator<Note> CREATOR = new Parcelable.Creator<Note>(){
#Override
public Note createFromParcel(Parcel source) {
return new Note(source);
}
#Override
public Note[] newArray(int size) {
return new Note[size];
}
};
}
and then in your activity
Activity A
intent.putExtra("NOTE", note);
Activity B
Note note = (Note) getIntent().getExtras().get("NOTE");
Imp: Parcelable is 10 times faster than Serializable

Can't debug a class that implements parcelable

If I have an object called "EditorialCollection" and it implements parcelable why can't I debug into the overrided methods like writeToParcel?
protected EditorialCollection(Parcel in) {
super(in);
//break point here:
items = new ArrayList<>();
in.readList(items, CollectionItem.class.getClassLoader());
embedPagination = (EmbedPagination) in.readValue(EmbedPagination.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<EditorialCollection> CREATOR = new Creator<EditorialCollection>() {
#Override
public EditorialCollection createFromParcel(Parcel in) {
return new EditorialCollection(in);
}
#Override
public EditorialCollection[] newArray(int size) {
return new EditorialCollection[size];
}
};
I can't hit break points nor can I output logging there. Am I doing something wrong or can someone explain why logging/breakpoints won't work here.
Thanks,
Reid
Parcel objects or Parcelable implementation objects cannot being debugged.
public final class Parcel {
private static final boolean DEBUG_RECYCLE = false;
private static final boolean DEBUG_ARRAY_MAP = false;
private static final String TAG = "Parcel";
.
.
.
}
You can use Parcelables.forceParcel(builder, CREATOR) method for testing Parcel classes.
But it is only available for Test Classes.
Also you can copy this func from Parcelables class. And you can try in java code:
public static <T extends Parcelable> T forceParcel(T parcelable, Creator<T> creator) {
Parcel parcel = Parcel.obtain();
try {
parcelable.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
return creator.createFromParcel(parcel);
} finally {
parcel.recycle();
}
}

How use object in multiple classes?

Im fighting with this some time and still don't know how to make it work. So i have class Player with constructor
Player(String playerName, double playerCash)
{
this.playerName = playerName;
this.playerCash = playerCash;
}
In MainActivity i make a player object
Player player = new Player("player", 100);
And now in TextView in SecondActivity i would like to use
playerCash = (TextView) findViewById(R.id.playerCash);
playerCash.setText(player.getPlayerCash());
Can someone explain me how i can make it works? I get cannot resolve symbol player. Thanks in advance
You can implement Parcelable interface for Player class and then pass instance of it from the MainActivity through Intent to the SecondActivity.
I am unsure if what you have posted is your entire class, or if you obviated a part of it. I will write this answer, assuming that is your entire class.
So, here is the deal: you need to create methods in your class for you to get and set data to/from it.
public class Player() implements Parcelable {
private String playerName;
private String playerCash;
public Player(String playerName, String playerCash) {
this.playerName = playerName;
this.playerCash = playerCash;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
public String getPlayerCash() {
return playerCash;
}
public void setPlayerCash(String playerCash) {
this.playerCash = playerCash;
}
public Player(Parcel in) {
String[] data = new String[2];
in.readStringArray(data);
this.playerData = data[0];
this.playerCash = data[1];
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {this.playerName,
this.playerCash});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Player createFromParcel(Parcel in) {
return new Player(in);
}
public Player[] newArray(int size) {
return new Player[size];
}
};
}
edit
I didn't read the part where you say you want to share it between Activities. I only noticed it because someone mentioned implementing Parcelable, which does help your problem.
Anyway, I edited my code to implement it.
To share data between Activities you will also need an intent, and there you can share the data stored on your Player class:
Intent i = new Intent();
i.putExtra("player", new Player("Jhon", "Over 9000!");
And in your 2nd Activity, to get it you would do:
Bundle b = getIntent().getExtras();
Player player = b.getParcelable("player");
Hope that helps.

What is the difference between `writeValue` and `writeParcelable`?

I have been searching for a way to pass an object from one Activity to another.
Different tutorials stated that the best way to do it is to make the class Parcelable. I've managed to implement it, but I have one question left.
There is a reference to another parcelable object (location) inside the Office class. This tutorial tells to serialize it using dest.writeParcelable(location, flags); and in.readParcelable(LatLng.class.getClassLoader());, but the parcelabler created the code with dest.writeValue(location); and then (LatLng) in.readValue(LatLng.class.getClassLoader());.
I have checked and it worked both ways.
Could somebody please explain what is the difference between these two approaches? Is any of them better for some reasons? Thank you!
public class Office implements Parcelable {
#SuppressWarnings("unused")
public static final Parcelable.Creator<Office> CREATOR = new Parcelable.Creator<Office>() {
#Override
public Office createFromParcel(Parcel in) {
return new Office(in);
}
#Override
public Office[] newArray(int size) {
return new Office[size];
}
};
public final String name;
public final String address;
public final LatLng location;
public Office(String name, String address, LatLng location) {
this.name = name;
this.address = address;
this.location = location;
}
protected Office(Parcel in) {
name = in.readString();
address = in.readString();
// location = (LatLng) in.readValue(LatLng.class.getClassLoader());
location = in.readParcelable(LatLng.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(address);
// dest.writeValue(location);
dest.writeParcelable(location, flags);
}
}
writeValue is more generic, and since it takes an Object as parameter, internally they check the instanceOf the object to call the specific method. If you know the type, I would stick with using the specific one

How to Pass Custom Arraylist content from one Activity to another Activity in android

i have an objects in an custom arraylist as "finaljsoncontent", and now i am trying to pass this "finaljsoncontent" array to another Activity, and i have also tried getters and setters, and also bundle, but i cant, help me how to do this.
Thanks in advance.
Check this out: How do I pass an object from one activity to another on Android?
Your class "JSonKey" should implement parcealable or serializable so that Android can "send" it from an activity to the other activity.
You could try implementing Parcelable, then you can pass it in a bundle. You will need to reduce your object to mostly primitive types to do this. Otherwise you can extend the Application class and store it there. You would retrieve that using the call to getApplicationContext(). Or, of course, you could always create some sort of static globals class that all of your classes can reference.
Here is one of my implementations of parcelable..
package warrior.mail.namespace;
import android.os.Parcel;
import android.os.Parcelable;
public class JView implements Parcelable {
public String subject;
public String from;
public boolean unread;
public String body;
public int inboxIndex;
private long id;
public static final Parcelable.Creator<JView> CREATOR = new Parcelable.Creator<JView>() {
public JView createFromParcel(Parcel in) {
return new JView(in);
}
public JView[] newArray(int size) {
return new JView[size];
}
};
public JView(){
body = "";
}
public JView(String subject,String from,boolean unread){
body = "";
this.subject = subject;
this.from = from;
this.unread = unread;
}
public JView(Parcel parcel){
subject = parcel.readString();
from = parcel.readString();
body = parcel.readString();
unread = parcel.createBooleanArray()[0];
inboxIndex = parcel.readInt();
}
#Override
public int describeContents() {
return inboxIndex;
}
#Override
public void writeToParcel(Parcel out, int arg1) {
out.writeString(subject);
out.writeString(from);
out.writeString(body);
boolean[] array = new boolean[] {unread};
out.writeBooleanArray(array);
out.writeInt(inboxIndex);
}
public void setIndex(int index){
inboxIndex = index;
}
public void setUnread(boolean arg){
unread = arg;
}
public void setContent(String content){
body = content;
}
public void setSubject(String subject){
this.subject = subject;
}
public void setFrom(String f){
from = f;
}
public void setId(long arg){
id = arg;
}
public long getId(){
return id;
}
public void updateIndex(){
}
}
You can either make your class Parcelable(android specific) or make it serializable like in java(just write implements Serializable with your class)

Categories

Resources