Putting serializable extra object to intent changes the object - android

I am trying to pass an object from an activity to another activity. Here is what i do:
MyApplication.db= dbToOpen;
Intent i = new Intent(mContext, OpenDbActivity.class);
i.putExtra("PARENT_GROUP", dbToOpen.root);
mContext.startActivity(i);
Here, MyApplication is the class that extends application, and db object is a static object. My extra object dbToOpen.root is an object of the class DBGroupv1.
Then i get this extra in onCreate method of OpenDbActivity class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_opendb);
db = MyApplication.db;
groupToOpen = (DBGroupv1) getIntent().getSerializableExtra("PARENT_GROUP");
}
Then i try this boolean expression:
MyApplication.db.root == groupToOpen
and it returns false. When i look at the objects dbToOpen.root and groupToOpen, every single value of the variables inside those objects are the same. But they are are different objects. Why is this happening? Is it because of casting, or does Intent.putextra() method passes a copy of an object, not a reference? If that is the case how can i pass the object as a reference?(Except using static variables)
Thanks

You should use the .equals()-method to compare instances of objects. if you use == you will only get true if the two objects are exactly the same reference. Since the instance in your intent is newly created when deserialized from the bundle, it is no longer a reference to the same instance (although the two objects contains the same data).
So, instead of
MyApplication.db.root == groupToOpen //bad
use
MyApplication.db.root.equals(groupToOpen) //good
Also make sure that if you made the root-object, you implement the equals method properly, so it takes all appropriate variables into consideration.
You can read a bit more here: What is the difference between == vs equals() in Java?

Related

Pass an interface from class to activity

If i have an object form interface in my class, how i can pass it to activity?
My solution was to change it as static object, it's work fine but sometimes it create a memory leaks because of all the old references which the garbage collector cannot collect, and i cannot implement 'Serializable' on my interface.
public class MyClass {
protected OnStringSetListener onstringPicked;
public interface OnStringSetListener {
void OnStringSet(String path);
}
//......//
public void startActivity(){
Intent intent=new Intent(context,Secound.class);
// ?! intent.putExtra("TAG", inter);
context.startActivity(intent);
}
}
In my opinion, using Bundles would be a nice choice. Actually bundles internally use Parcelables. So, this approach would be a good way to go with.
Suppose you would like to pass an object of type class MyClass to another Activity, all you need is adding two methods for compressing/uncompressing to/from a bundle.
To Bundle:
public Bundle toBundle(){
Bundle bundle = new Bundle();
// Add the class properties to the bundle
return bundle;
}
From Bundle:
public static MyClass fromBundle(Bundle bundle){
MyClass obj = new MyClass();
// populate properties here
return obj;
}
Note: Then you can simply pass bundles to another activities using putExtra. Note that handling bundles is much simpler than Parcelables.
Passing in custom objects is a little more complicated. You could just mark the class as Serializable
and let Java take care of this. However, on the android, there is a serious performance hit that comes with using Serializable. The solution is to use Parcelable.
Extra info

passing variable status between classes

I am making a boolean variable value in one class and accessing the status of that variable in another class , on the basis of the boolean variable status my list view shows items,
So my question is
how to create a global boolean varible
how to pass it to another class
how the second class check it
1. Variable in class A
public class A{
public String aClassVar="hello";
}
Using it in Class B
A obj=new A();
String inBClass=obj.aClassVar;
2. To pass data from one Activity to Another Activity you can use Intent remember your Class should extends Activity only than you will be able to pass data by using Intent
Example
Send Data From First Activity using :
Intent i = new Intent(this, SecondClassName.class);
i.putExtra("key", "Value");// key is used to get value in Second Activiyt
startActivity(i);
Receive Data on Second Activity using:
Intent intent = getIntent();
String temp = intent.getStringExtra("key");// usr getStringExtra() If your extra data is represented as strings:
And you Must set Activity Name inside AndroidManifest.xml
like:
<activity android:name="yourPackageName.SecondClassName" />
Let me suggest 3 options.
Do you want to pass a boolean variable between Android Activities? If so, You may want to use a Bundle. Yes, those little things given to Activities on onCreate(). You can pass variables of your own into these, in your case a boolean, with putBoolean() and getBoolean()
Would you prefer using Android's SharedPref? It's an interface for sharing small preferences, like boolean flags, between parts of your app and storing it for later.
Or, you could just implement a singleton class that has the boolean variable and other variables you need to store and check by different classes within your app.
If you just want to access the value of an object or variable in another class, make it Static and then when you need its value, do like
public class tempClass {
public void tempMethod() {
boolean status = myClass.myVariable ; // where myVariable is static boolean varaible of myClass
}
}
But make sure to access the variable after some value is stored in it.
If you want to send the value to another activity then send the value by using intent.
Eg.
Bundle myBund = new Bundle();
myBund.putBoolean(myBool);
Intent intent = new Intent(myClass.this, tempClass.class);
intent.putExtras("myKey",myBund);
startActivity(myBund);

when is an object created and can be referenced to?

I have a simple question but can't find the solution in the references anywhere.
When I create an instance of a certain class where the instance is to be propagated to a couple of places everytime it is created again the most obvious place where to put the code is in the creation method of the instance itself. This is how it would look like:
public void MYTest() {
public MYTEST() {
ANOTHER_CLASS.myTest = this; // <-------- can I already use the new this and assign it ?
}
}
Can I put the assignments of this just newly created instance to other variables already in the creation method or do I have to write an extra "super" creation method like this and put this also in MYTEST:
public void MYTest() {
public MYTEST() {
ANOTHER_CLASS.myTest = this; // <-------- can I already use the new this and assign it ?
}
public static MYTEST superCreationMethodForMYTEST() {
x = new MYTEST(); // <- here for sure the creation of MYTEST instance is finished BEFORE the assgnment happens
ANOTHER_ClASS.myTest = x;
.... all the other assignments for x.....
}
}
and then call it like
x = MYTEST.superCreationMethodForMYTEST();
instead of:
x = new MYTEST();
Thanks
You can assign the this reference anywhere in the constructor. However, it may not be wise, depending on your situation. The main problem is that while the object exists at the time of the constructor, it is not completely constructed and therefore may not be in a state to handle method calls correctly. If the assigned reference is used by an unsuspecting thread, for example, (or by a method called by your constructor) before your constructor (and any subclass constructors) finish, bad things may happen.
Edited to add: Your problem, as I understand it, is to make sure that a reference to the object is stored in particular places before whoever requested the creation of the object receives the newly created object. One common pattern is to do basically what you surmise in your question, namely having a factory method (a static method) that uses new to construct the object and then stores it in the appropriate places. This ensures that only references to a fully constructed object is stored. At the same time, the actual constructor is declared private or protected to prevent accidental use of new outside the factory method.

Android: Intent with parameters

To pass parameters from one activity to another is used the method "intent.putExtra()"
Does this method only allows to add primitive data or I can add a parameter that is a java bean?
if you can not, how I can send a java bean from one activity to another?
Thanks!!
Look at the API entry for Intent. You've got a load of possible data types you can enter, not the least of which is Parcebles, Bundles, and Serializable. If you really want simple object marshalling I would convert your beans to JSON and put it as a String, then convert it back to a POJO on the receiving end.
You can send objects if they implements serializable.
//At your entity Object:
public class Objeto implements Serializable{
}
//At the sender Activity:
//create an instance of the object
Objeto object = new Objeto();
//creates an intent from the current activity to the destiny activity with the data to be transferred.
Intent proximo = new Intent(this,TelaDestino.class);
//transfers the object as a bundle to the next activity
proximo.putExtra("OBJETO",objeto);
startActivity(proximo);
//At the destine activity:
private Objeto objeto;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
objeto = (Objeto)getIntent().getSerializableExtra("OBJETO");
}
//You can use that and be happy :D
If your object is is Serializable you can add it with putExtra like this.
i.putExtra(String key, Serializable value);
Another way to share data between activities is extend the application class.
My answer explains how to use it.
getApplicaiton return which object among applicaitons

Regarding Intents

According to what i have learnt from passing data using Intents is that when you pass Object O from Activity A to Activity B via intents, activity B receives a COPY of object O. The way things work is that The object O gets serialized (converted to a sequence of bytes) and that sequence of bytes is then passed to Activity B. Then activity B recreates a copy of object O at the moment it was serialized.
I would like to know if it would be efficient if one extends the Intent class to create a custom Intent and have references to the objects that are required by the other activities and pass the data to the other activities. For example:
public class CustomIntent extends Intent {
private Object o;
public CustomIntent() {
super();
// TODO Auto-generated constructor stub
}
public Object getObject () {
return o;
}
public void setObject(Object object) {
this.o = object;
}
}
In the receiving activity i get the intent and cast the intent to the CustomIntent type and retrieve the object required by the activity. Would this improve the efficiency by reducing the need for Serialization? Kindly throw some light on this. Thanks in advance.
No. Intents are dispatched by the Android system and are always serialized as they can be sent to any activity, service, etc in the system.
For your problem you could probably workaround this issue by creating an Application class and storing your data in it:
class CustomApplication extends Application {
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
You activate it by updating AndroindManifest.xml setting the android:name property on the application tag you your class name.
To use in your activities:
CustomApplication app = (CustomApplication) getApplicationContext();
app.setData(yourDataObject);
I think it would be better if you let the android handle everything for you. Do not customize it, if it is not very essential.
If you want to have the reference of the object in another activity then there are other ways too.
You can make your object static and directly access it from other activity.
You can make a new object of same type and replace it after coming again back to the first activity(in onActivitResult() method.).
or there may be many more ways to do it.
Thanks.

Categories

Resources