I am having a class EmployeeInfo as the following:
public class EmployeeInfo {
private int id; // Employee ID
private String name; // Employee Name
private int age;// Employee Age
public int getEmployeeID() {
return id;
}
public void setEmployeeID(int id) {
this.id = id;
}
public String getEmployeeName() {
return name;
}
public void setEmployeeName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age= age;
}
}
ArrayList<EmployeeInfo> employeeInfo object contains the emplyoyee info data for multiple employees.
I want to transfer the data( ArrayList employeeInfo ) from Activity1 to Activity2.
Is using Parcelable the only way to transfer the data from Activity1 to Activity2?
If not , what are the alternatives.
If yes ,kindly provide the prototype code of Parcelable along with the sample code on how to transfer the object data from Activity1 to Activity2.
Here is my implementation of Parceleble:
public class ProfileData implements Parcelable {
private int gender;
private String name;
private String birthDate;
public ProfileData(Parcel source) {
gender = source.readInt();
name = source.readString();
birthDate = source.readString();
}
public ProfileData(int dataGender, String dataName, String dataBDate) {
gender = dataGender;
name = dataName;
birthDate = dataBDate;
}
// Getters and Setters are here
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(gender);
out.writeString(name);
out.writeString(birthDate);
}
public static final Parcelable.Creator<ProfileData> CREATOR
= new Parcelable.Creator<ProfileData>() {
public ProfileData createFromParcel(Parcel in) {
return new ProfileData(in);
}
public ProfileData[] newArray(int size) {
return new ProfileData[size];
}
};
}
and how I transfer data:
Intent parcelIntent = new Intent().setClass(ActivityA.this, ActivityB.class);
ProfileData data = new ProfileData(profile.gender, profile.getFullName(), profile.birthDate);
parcelIntent.putExtra("profile_details", data);
startActivity(parcelIntent);
and take data:
Bundle data = getIntent().getExtras();
ProfileData profile = data.getParcelable("profile_details");
You can simply let your EmployeeInfo class implement Serializable. Or you can send data like this
intent.putExtra("id", employInfo.getEmployeeID());
intent.putExtra("name", employInfo.getEmployeeName());
intent.putExtra("age", employInfo.getAge());
If you need to transfer a list of your custom classes, i'd use the first approach. So you would be able to put entire list as Serializable.
However they said that everyone should use Parcelable instead because it's "way faster". Tbh, I'd never used it, because it needs more effort and I doubt somebody can realize the difference in speed in a regular application w/o a load of data sending via intent
Good question. Looking at the docs and doing armchair coding:
It may be possible to pass an object between Activities by calling putExtras(Bundle) and myBundle.putSerializable. The object and the entire object tree would need to implement serializable.
JAL
EDIT: The answer is yes:
It is possible to pass an immutable object between Activities by calling putExtras(Bundle) and myBundle.putSerializable. The object and the entire object tree would need to implement serializable. This is a basic tenet of Object Oriented Programming, passing of stateful messages.
First we create the immutable object by declaring a new class:
package jalcomputing.confusetext;
import java.io.Serializable;
/*
* Immutable messaging object to pass state from Activity Main to Activity ManageKeys
* No error checking
*/
public final class MainManageKeysMessage implements Serializable {
private static final long serialVersionUID = 1L;
public final int lengthPassword;
public final long timeExpire;
public final boolean isValidKey;
public final int timeoutType;
public MainManageKeysMessage(int lengthPassword, long timeExpire, boolean isValidKey, int timeoutType){
this.lengthPassword= lengthPassword;
this.timeExpire= timeExpire;
this.isValidKey= isValidKey;
this.timeoutType= timeoutType;
}
}
Then we create an immutable stateful instance of the class, a message, in the parent activity, and send it in an intent as in:
private void LaunchManageKeys() {
Intent i= new Intent(this, ManageKeys.class); // no param constructor
// push data (4)
MainManageKeysMessage message= new MainManageKeysMessage(lengthPassword,timeExpire,isValidKey,timeoutType);
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.MainManageKeysMessage", message);
i.putExtras(b);
startActivityForResult(i,REQUEST_MANAGE_KEYS); // used for callback
}
Finally, we retrieve the object in the child activity.
try {
inMessage= (MainManageKeysMessage) getIntent().getSerializableExtra("jalcomputing.confusetext.MainManageKeysMessage");
lengthPassword= inMessage.lengthPassword;
timeoutType= inMessage.timeoutType;
isValidKey= inMessage.isValidKey;
timeExpire= inMessage.timeExpire;
} catch(Exception e){
lengthPassword= -1;
timeoutType= TIMEOUT_NEVER;
isValidKey= true;
timeExpire= LONG_YEAR_MILLIS;
}
Well there is another way to transfer an object.We can use application to transfer object and this is way is far better way in my opinion.
First of all create your custom application in your main package.
public class TestApplication extends Application {
private Object transferObj;
#Override
public void onCreate() {
super.onCreate();
// ACRA.init(this);
}
public Object getTransferObj() {
return transferObj;
}
public void setTransferObj(Object transferObj) {
this.transferObj = transferObj;
}
}
Now use setTransfer and get transfer methods to move abjects from one activity to other like:
To Transfer:
((TestApplication) activity.getApplication()).setTransferObj(Yous object);
ToRecieve:
Object obj=((TestApplication) activity.getApplication()).getTransferObj();
NOTE
Always remember to make entry of this application in manifest application tag:
<application
android:name=".TestApplication">
</application>
You can convert your object to jsonstring using Gson or Jakson and pass using intent as string and read the json in another activity.
Related
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
I need to pass a large list of data from one activity to another activity,which way is better?
First way(for example):
ArrayList<myModel> myList = new ArrayList<myModel>();
intent.putExtra("mylist", myList);
Second way(for example) :
ActivityTwo act = new ActivityTwo();
act.getDataMethod(listValues);
Intent i = new Intent(this, ActivityTwo.class);
startActivity(i);
And in another activity(ActivityTwo) I get data from getDataMethod.
If the data you want to send is really big (around 1MB). The best way to pass it is to store it in persistent storage in ActivityA and access it in ActivityB.
The approach with passing it via Parcerable/Serializable is risky as you may end up with TransactionTooLargeException when trying to pass around 1MB of data.
The approach with passing it via Singleton class is even worse as when you are in ActivityB and application is recreated (it was long in background/memory was low) you will loose data from singleton (process is recreated) and nobody will set it, ActivityB will be launched and it wont have data from AcitvityA (as it was never created).
In general you shouldn't pass data through intents, you should pass arguments/identifiers which then you can use to fetch data from db/network/etc.
Best way to pass large data list from one Activity to another in Android is Parcelable . You first create Parcelable pojo class and then create Array-List and pass into bundle like key and value pair and then pass bundle into intent extras.
Below I put one sample User Pojo class that implements Parcelable interface.
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by CHETAN JOSHI on 2/1/2017.
*/
public class User implements Parcelable {
private String city;
private String name;
private int age;
public User(String city, String name, int age) {
super();
this.city = city;
this.name = name;
this.age = age;
}
public User(){
super();
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#SuppressWarnings("unused")
public User(Parcel in) {
this();
readFromParcel(in);
}
private void readFromParcel(Parcel in) {
this.city = in.readString();
this.name = in.readString();
this.age = in.readInt();
}
public int describeContents() {
return 0;
}
public final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
public User createFromParcel(Parcel in) {
return new User(in);
}
public User[] newArray(int size) {
return new User[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(city);
dest.writeString(name);
dest.writeInt(age);
}
}
ArrayList<User> info = new ArrayList<User>();
info .add(new User("kolkata","Jhon",25));
info .add(new User("newyork","smith",26));
info .add(new User("london","kavin",25));
info .add(new User("toranto","meriyan",30));
Intent intent = new Intent(MyActivity.this,NextActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("user_list",info );
intent.putExtras(bundle);`
startActivity(intent );
To me serialized objects/list is better way.
`Intent intent = ....
Bundle bundle = new Bundle();
ArrayList<String> myList = new ArrayList<String>();
bundle.putSerializable("mylist", myList);
intent.putExtras(bundle);`
Use the first approach. However you will need to use the following method call to put it into the Intent:
ArrayList<String> myList = new ArrayList<String>();
intent.putStringArrayListExtra("mylist",myList);
The to get the list out of the intent in the receiving Activity:
ArrayList<String> myList = getIntent().getStringArrayListExtra("mylist");
If you have a huge list of data it is better way to save the data in Singleton java class and use set/get to save & get the data in application level.
Sharing large data as intent bundle may chances to lose data.
Application.class
add this in you manifest file
<application
android:name=".App"
-----
</application>
public class App extends Application {
public ArrayList<Object> newsList;
#Override
public void onCreate() {
super.onCreate();
}
public void setHugeData(ArrayList<Object> list){
this.newsList = list;
}
public ArrayList<Object> getHugeData(){
return newsList;
}
}
in ActivityA.class
ArrayList<Object> info = new ArrayList<>();
// save data
((App)getApplication()).setHugeData(info);
in ActvityB.class
ArrayList<Object> info = new ArrayList<>();
// get the data
info = ((App)getApplication()).getHugeData();
You can use such libraries as Eventbus to pass models through activities or you can put your model in ContentValues (https://developer.android.com/reference/android/content/ContentValues.html) class - it is parcable and you can pass it through intent. A good practice is to implement two methods in your Model class - toContentValues() and fromContentValues().
Something like this:
public class DealShort extends BaseResponse implements ContentValuesProvider {
#SerializedName("id")
#Expose
private long id = -1;
#SerializedName("full_price")
#Expose
private double fullPrice;
public static DealShort fromContentValues(ContentValues cv) {
DealShort deal = new DealShort();
deal.id = cv.getAsLong(DbContract.Product.SERVER_ID);
deal.fullPrice = cv.getAsLong(DbContract.CategoriesProducts.CATEGORY_ID);
}
public ContentValues toContentValues() {
ContentValues cv = new ContentValues();
cv.put(DbContract.Product.SERVER_ID, id);
cv.put(DbContract.Product.FULL_PRICE, fullPrice);
return cv;
}
}
1,You can use Singleton class,like below code:
public class MusicListHolder {
private ArrayList<MusicInfo> musicInfoList;
public ArrayList<MusicInfo> getMusicInfoList() {
return musicInfoList;
}
public void setMusicInfoList(ArrayList<MusicInfo> musicInfoList) {
this.musicInfoList = musicInfoList;
}
private static final MusicListHolder holder = new MusicListHolder();
public static MusicListHolder getInstance() {
return holder;
}
}
it's easy and useful!
2,You can use Application,just put your data in Application before you use it!
3,You can use Eventbus
4,You can put your data in a file/sqlite/...,maybe it's slow and conflict,but it's workable
I'm begginer in Android and i try to pass object between activities with object contains other objects but errors appear.
A solution?
I try to pass object with serializable :
lALL.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View v,
int position, long arg3) {
System.out.println(position);
Locataire l = new Locataire(getResources());
l.setNom("test");
l.setPrenom("test");
Intent intent = new Intent(MainActivity.this, Etat_lieux.class);
intent.putExtra("EDL", l);
startActivity(intent);
}
});
And
public class Locataire implements Serializable{
private String ref;
private String civilite;
private String nom;
private String prenom;
private Contact contact = new Contact();
private Adresse adresse = new Adresse();
private String DG;
private boolean IsGarantPresent;
private boolean IsColocation;
private Resources res;
public Locataire(Resources res)
{
this.res = res;
}
Contact,Adresse
public class Contact implements Serializable{
protected String tel;
protected String mobile;
protected String fax;
protected String email;
protected String www;
And ressource is Context getResources() of first activity
If you want to pass data between activities in your own app you should use startActivity, startActivityForResult and onActivityResult. You create a Bundle object and encapsulate your data in it with putExtra. Then you retrieve this object in your onCreate method.
http://developer.android.com/training/basics/intents/result.html
Otherwise, if you want to pass data between activities in your app and activities in another app you should use explicit or implicit intents.
http://developer.android.com/training/basics/intents/sending.html
If you want to pass object in extras... you have to make the object implements serializable..and make all it sub-objects implement serializalbe..
then use bundle.putSerializable(OBJECT)..
I am trying to pass my own custom object into a bundle:
Bundle b = new Bundle();
STMessage message = (STMessage)a.getAdapter().getItem(position);
b.putObject("message",message);
I get the error:
The method putObject(String, Object) is undefined for the type Bundle
One way is to have your custom object implement the Parcelable interface and use Bundle.putParcelable/Bundle.getParcelable
Model Class
package com.sam.bundleobjectpass;
import java.io.Serializable;
/**
* Created by Samir on 31.8.2016.
*/
public class Model implements Serializable {
private String name;
private String surName;
private int age;
public Model(String name, String surName, int age) {
this.name = name;
this.surName = surName;
this.age = age;
}
public String getName() {
return name;
}
public String getSurName() {
return surName;
}
public int getAge() {
return age;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Model model = new Model("Sam", "Sami",32);
Intent i = new Intent(MainActivity.this, ReceiverActivity.class);
i.putExtra("Editing", model); // sending our object. In Kotlin is the same
startActivity(i);
}
}
ReceiverActivity
public class ReceiverActivity extends Activity {
TextView txt_name;
TextView txt_surname;
TextView txt_age;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
txt_name = (TextView)findViewById(R.id.txt_name);
txt_surname = (TextView)findViewById(R.id.txt_surname);
txt_age = (TextView)findViewById(R.id.txt_age);
// receiving our object
Model model = (Model) getIntent().getSerializableExtra("Editing");
txt_name.setText(model.getName());
txt_surname.setText(model.getSurName());
txt_age.setText(""+model.getAge());
}
}
// Kotlin
val model: ProgramModel? = intent.getSerializableExtra("Editing") as ProgramModel?
model?.let { // means if not null or empty
txt_act_daily_topic.text = it.title
}
Since using Parsable is designed for high performance IPC transport as mentioned in some of the comments, I tried using a different approach.
My approach uses GSON library by google.
Example
public class Person{
private String name;
private int age;
// Getter and Setters omitted
}
You can have a method in utility class that returns Gson instance, this is for the sake of clean code and organisation. I will use GsonBuilder incase someone what to register custom adapter.
public class Utils {
private static Gson gson;
public static Gson getGsonParser() {
if(null == gson) {
GsonBuilder builder = new GsonBuilder();
gson = builder.create();
}
return gson;
}
}
Moment of truth!
PUT
Bundle args = new Bundle();
String personJsonString = Utils.getGsonParser().toJson(person);
args.putString(PERSON_KEY, personJsonString);
GET
Bundle args = getArguments();
String personJsonString = args.getString(PERSON_KEY);
Person person= Utils.getGsonParser().fromJson(personJsonString, Person.class);
Currently I don't know the performance limitation of this approach. But it works just fine
Make your custom object Parcelable or Serializable then use putParcelable or putSerializable.
Depending on the complexity of your object one or other may be easier.
As Ryan stated. Also if you only want to pass one object on a soft kill consider using onRetainConfigurationInstance and getLastNonConfigurationInstance to pass the serializable object. The entire object tree must be serializable. If you are passing the object via an intent, consider refactoring the object code to a Parceable code later, once the architecture has stabilized. Finally, consider using the fully qualified name of the class when storing the object into the Bundle as in:
inPWState= (PasswordState) getIntent().getSerializableExtra("jalcomputing.confusetext.PasswordState");
Hope that helps.
JAL
It's work
if you make your object class as Serializable
class your_data_class implements Serializable
In my application I am fetching data from JavaScript, as it is not possible to return the data as an array or object, I am returning it as a String.
Now to organize the data I am creating a class which contains ArrayLists and other string variables and further I am creating array of my class objects variable to store multiple records.
public class Data {
ArrayList<String> m_empArrayList = new ArrayList();
ArrayList<String> m_depArrayList = new ArrayList();
String m_time;
String m_duration;
}
Data d = new Data();
What would be a good approach to pass the data between Activities? As Intents and ShredPrefrences are used to pass small units of data I am not considering it here.
Implement the Parcelable interface in your custom object and transmit it via an Intent.
Here is an example of a Parcelable object.
public class MyObject implements Parcelable {
private String someString = null;
private int someInteger = 0;
public MyObject() {
// perform initialization if necessary
}
private MyObject(Parcel in) {
someString = in.readString();
someInteger = in.readInt();
}
public static final Parcelable.Creator<MyObject> CREATOR =
new Parcelable.Creator<MyObject>() {
#Override
public MyObject createFromParcel(Parcel source) {
return new MyObject(source);
}
#Override
public MyObject[] newArray(int size) {
return new MyObject[size];
}
};
// Getters and setters
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(someString);
dest.writeInt(someInteger);
}
}
Here is what happens. If you implement the Parcelable interface you have to create a private constructor which takes a Parcel as a parameter. That Parcel holds all the serialized values.
You must implement the nested class Parcelable.Creator with the name CREATOR as this is going to be called by Android when recreating your object.
The method describeContents() is only of use in special cases. You can leave it as it is with a return value of 0.
The interesting action happens in writeToParcel() where you, as the name tells, write your data to a Parcel object.
Now you can just add your custom object directly to an Intent like in this example.
MyObject myObject = new MyObject();
Intent i = new Intent();
i.setExtra("MY_OBJECT", myObject);
// implicit or explicit destination declaration
startActivity(i);
you can use Application class present in Android to pass data between activities.
here is a good link..http://www.helloandroid.com/tutorials/maintaining-global-application-state