It took me forever to figure this out, but I'm noticing that when I pass an object in as an Extra to an Intent (in my case, an object extending Parcelable), for whatever reason it creates a new object in memory as opposed to holding onto the same object reference.
Is there a way to get it to retain the reference?
for whatever reason it creates a new object in memory as opposed to holding onto the same object reference
That depends on what you are doing with the Intent. If you are passing it as a parameter to your own method, or otherwise using it purely in-process (e.g., LocalBroadcastManager), it should not copy the extras.
However, my guess is that you are doing something like:
startActivity() and its various flavors (e.g., startActivityForResult())
startService()
bindService()
sendBroadcast() called on a Context
wrapping the Intent in a PendingIntent and using that PendingIntent somewhere (e.g., as part of a Notification)
In all of these cases, your Intent data is passed outside of your app's process to a central OS process. This requires the data to be copied. If relevant (e.g., the activity you are starting is one of your own), the Intent data is passed back from the central OS process to your process, making another copy in your process.
In these scenarios, the copying is unavoidable.
The problem is that if I update the object in the second Activity, I want it to also be updated back in the first activity.
Either:
Do not have separate activities here, or
Do not pass the object by means of an Intent extra (e.g., have a central cache of model objects, and pass the ID of the model in an extra, so the other activity can pull the object from the cache)
Related
Title pretty much says it all. I need to pass a listener object defined in one activity to the new activity I'm starting. You can't use serialization for obvious reasons (you'd be notifying the clone, not the original) but I'm not sure how to either send over the object to the new activity, or get the new activity from the old one.
Only solution I've seen so far is to set a static on the new activity, then when the new activity starts up, grab it from the static. It just feels 'icky' to me, although if you simply set the static, then launch the new activity, you shouldn't run into stateful bugs.
The other is to use local notifications, passing along a notification key, which can be serialized since it's just a key, then set up listeners for it, but that seems to be like driving an 18-wheel semi to the store just to get some milk.
I just keep thinking there has to be a better way. Is there?
Store it in a singleton or via some injection method like Dagger. You cannot pass an instance via Intent- since an Activity could thoeretically be started by any other process, there's no way to pass instances between two activities in the Intent.
I have a number of classes that implement the Parcelable interface so that I can pass instances of those objects between activities. I'm trying to understand how this does/does not cause a memory leak.
If an object is create in one activity and passed via Intent to another, I would guess this would pass a reference to that object. Based on my (potentially wrong) understanding of how the garbage collector works, this would create a reference from the receiving activity to the sending activity and create a memory leak as the sending activity could not be garbage collected in that state.
What am I missing?
If an object is create in one activity and passed via Intent to another, I would guess this would pass a reference to that object.
AFAIK, no, because activity creation goes by way of a core OS process. I would expect a copy to be made as a result of this, with a side effect of not having the GC issue you outlined.
My app contains 2 activitys. Activity A is the one which is created by starting the app. In this one I create an object of my own class MyClass. This class contains one string and 3 integers. In activity A this object gets written.
The second activity B needs to read this object. How can I pass it from A to B? Or is there an other solution?
There are couple of way you can pass an object from one activity to another:
1. Application Class: this class is visible to all your application Activities so you can save your object in this class from one Activity and then access it from the other.
2. You can break apart your Class into the simple variables: string and 3 integers and pass them via a bundle or the intent it self from one activity to another, then construct your object again.
Intent intent = new Intent (this, TargetActivity.class);
intent.putExtra(KEY, value);
intent.putExtra(KEY, "value");
startActivity(intent);
3. If your object implements Serializable/Parcelable then you can pass it via a bundle.
Example on how to serialize an object:
How do I serialize an object and save it to a file in Android?
One option could be implementing Serializable interface and then you can pass object instances in intent extra using putExtra(Serializable..) variant of the Intent#putExtra() method.
//to pass :
intent.putExtra("MyClass", obj);
// to retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
It can be tricky, because there's no guarantee that your application can't be killed between activities. Actually, it can be killed during activities, so keeping persistent objects around can be tricky.
My preferred way to do this is the "singleton pattern" in which you create a class whose purpose is to create a single instance that holds whatever data you want to hang around. If your application gets killed, the singleton instance will be lost and have to be re-created, but all Android apps run this risk all the time anyway.
See Save multiple instances states of the same Activity in Android for my implementation of a singleton in Android.
Oh, and I should add that this only works within an application where all the activities are in the same process, sharing the same address space. Otherwise, you'll have to make your object serialiazable and write it off to a file.
In order to pass an object to an Activity, object must implement Parcelable/Serializable (or JSON-encoded, or whatever casts the object to a scalar).
(I know the alternative of using singletons, statics and so on.)
Why it is not possible to give a POJO to my Activity, something like new Intent( ... , myObject) or startActivity(intent, myObject) ?
I turned #Jens's comment into a community wiki:
Your call to startActivity is passed through to ActivityManagerNative - which, in turn, communicates with the activity manager service that runs in a completely different process - thus forcing whatever you put in your Intent to be Parcelable or Serializable
I have asked this question a few times on here already, but still am not confident enough to start throwing things into my code because I'm afraid I'll ruin the functionality it already has.
What I want to do is have a Bluetooth connection with a device that I can send/receive data to/from, and be able to access it from several different Activities. I know Intents can be used, but can anyone try to explain how intents work?
I don't understand how if I start with an Activity, how I can build an object within that Activity, then end it, and still have the object. When I call the intent in the following Activity, how do I access it?
I can not find example code of an Activity with a custom object that is passed through an intent, opened in another Activity, then passed again through another Activity, and so on. All I can find is things for string's, int's and it seems that those methods are hardcoded for the specific objects.
Any help would be greatly appreciated, thanks.
If you want to pass a custom object from an Activity to another one, your object have to implement Parcelable interface.
Here you can find an example of an object which implements Parcelable.
Once you have an instance of this object you can add it to an intent and pass it to other activity.
Let's say you have 2 activities: A and B.
If you want to send a custom object from A to B try put your parceable object in an intent and get it back in Activity B.
// Activity A
Notebook myNotebook = new Notebook(); // the "Parcelable" object
Intent intent = new Intent(A.this, B.class);
intent.putExtra("object", myNotebook);
startActivityForResult(intent);
// Activity B
// in onCreate method
Notebook notebook = intent.getParcelableExtra("object");
there is a good reason you don't find a good example of transfering complicate objects: you don't suppose to that a lot. it's possible to transfer with intent extra any object, with declare the class you want to transfer as implements Serializable, or Parcalable.
but - this is not recomended doing so, unless you have good reason.
there are unlimited ways to create "cross activities" objects (databases, singeltones, services..), and passing complicated objects in intent is heavy operation. also it makes terrible performances doing so.
anyway - if you want anyway doing so, that's the way:
this is how to pass serlizable object:
Intent intent = new Intent();
intent.putExtra(name, someInstanceOfClassWhichImplementsSerializableInterface);
this is how to acheive it on the other activity:
getIntent().getSerializableExtra(name);
about the question that you don't understand how the object still lives after you finish the activity - finish() activity is not triggering distractor!!!, but do triggers to onDestoy() callback. the system decides when it's the right time call the activities distracor , and even if it was distractor - it's not preventing from the Intent object to stay alive - because nobody said your activity is the only one holding reference to it. the intent reference held by the system for the perpose of passing it to the new activity which opened with it.
Using intent you can send serialized object which is like converting you object into byte stream. If you want to send your object as it is you can use handlers.
e.g.
create Bluetooth connection using service(android service)
define handler in you activity which will be static object
from service to send the object add to msg.obj send that msg to handler