I have a GAE backend and an Android client. I have generated the client library successfully and that works fine. Now, I'm trying to send an object via an intent from one activity to another in Android. To my horror I noticed that the generated GAE models are final classes that don't implement parcelable or serializable interfaces. Because of that I decided to try and use gson to parse them to json string and then back to the original object. That however fails on fields like DateTime for some reason. My next try was to just let the classes implement serializable (bad idea to touch generated classes!!) but the issue with that was that since these classes extend AbstractMap the serializable output is a HashMap rather than my original object! Now I'm thinking about letting it implement Parcelable but that's a lot of work and sounds like a very bad idea since these models are generated and could change (thus removing my parcelable work.)
I know that people here love code so here is my problem written in code:
Activity A (MainActivity) is trying to send a "UserScore" object (generated from GAE) to activity B.
Intent intent = new Intent(MainActivity.this, ResultsActivity.class);
intent.putExtra(ResultsActivity.BUNDLE_USERSCORE, userScore);
startActivityForResult(intent, REQUEST_COUNTDOWN);
This would've given my error since userScore isn't parcelable or serializable but in this case I made it serializable. Activity B (ResultsActivity) receives:
Object extra = getIntent().getSerializableExtra(BUNDLE_USERSCORE);
Now you would expect the extra object to be of the type UserScore but since it was sent via intent and is a subclass of AbstractMap it is in fact a HashMap.
So, my question is: has anybody encountered this issue and found a way to properly send GAE models via intents in android?
Related
Can anybody please tell why we need to serializable object for passing one activity to another activity in android? Android is following Java syntax. In java we can pass object to another class without serializable.
Thanks
In ordinary java programs passing parameters(Object type), is kind of create a new handler to the object and giving to another method (In regular words passing the reference by value).
But when it comes in android, passing object references from activity to activity, where their states have to be persisted, is a serious headache.
One way you can do is create a static object in the first activity and access from the second, though this seems to be a easiest way, there is no guarantee that the system maintains the activity in the memory. Therefore the second activity may loose the object reference.
Other way, and the mostly recommended way is serializing(Kind of flatten the object) the object and pass with the intent as extra. In android there are two ways to serialize.
Implement the java's serializable interface
Implement the android's parcelable interface
However, on the android, there is a serious performance hit that comes with using serializable, the solution is using parcelable.
You can find a pretty good tutorial and explanation on android parcelable implementation here.
We need to understand following concepts before getting to the answer:
Android uses Binder for inter-process process. It is required even for simple app because the OS and the apps run in different processes.
Marshalling:
A procedure for converting higher level application data structures into parcels for purpose of embedding into Binder transaction
Unmarshalling
A procedure for reconstructing higher-level application data-structures from parcels received though binder transactions.
You can consider Intents as higher level abstraction of Binder
Based on the documentation following is the way how intent communication occurs:
Activity A creates an Intent with an action description and passes
it to startActivity().
The Android System searches all apps for an intent filter that
matches the intent. When a match is found,
the system starts the matching activity (Activity B) by invoking
its onCreate() method and passing it the Intent.
Why Parcelable or Serializable
IPC (Inter Process Communication) requires data in Intent to be Marshalled and unMarshalled. Binder provides built-in support for marshalling many common data-types. However when we define custom object, it would impact this process and the final object received might be corrupted during the process.
When you define custom object, you need to be responsible for providing this marshalling and unmarshalling which is achieved through Parcelable and Serializable (Since comparison between these two would be another topic I won't discuss much here). Both of these provide mechanisms to perform marshalling and unmarshalling. This is the reason why you need to use Parcelable or Serializable.
Using Parcelable you write the custom code for marshalling and unmarshalling the object thereby you gain complete control over the process.
Serializable is a marker interface, which implies the user cannot marshall the data according to their requirements and its done on JVM, which doesn't give any control at your side.
Disclaimer: Description above is my understanding for the rationale behind the need for serialization based on some
documentation
There are basically two questions in your question, so let's decouple it.
Why marshall in a Parcelable instead of passing an object reference directly?
It's obvious faster and more memory efficient to reference objects rather than marshall/unmarshall them. So you shouldn't use Parcelable when you can pass the object directly.
However, there are situations where you may not have access to the object reference.
in Intent because the process that handles the Intent may not be the process that emitted the Intent (it's an inter-process communication)
in Activity lifecycle, for instance in onRestoreState(), because the whole app may have been killed by memkiller when the user wants to resume it.
everywhere else where Android frameworks requires
In IPC, why use Parcelable rather than Serializable like Java does?
That's only a performance optimization.
If We want to pass object from Activity to to Another Activity . We need to save the passing state.
//to pass :
intent.putExtra("MyClass", obj);
// to retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
I am using Retrofit with Gson to get some data from my server in my Splash activity.
Now when the call is complete it writes data to Gson Model Classes automatically,
Right Now I have made static ArrayLists of those model classes and writes data to them from call response but this doesn't sound like a good approach.
I was wondering what is the better approach to solve this problem?
Is there Anyway I can get data from these Model Classes directly in other activities using Gson?
or I would have to send them from one activity to other? if so then how can I send them as they already have Serialized annotation.
Thanks
There're more possible solutions how to solve this:
1) Use EventBus (for example Otto Bus) and pass it via this. You also can use RxJava and Observable pattern, but this requires more work.
2) Create a DataHolder singleton, store data in it and use it everywhere you need
3) Pass it via an Intent to Activity
I personally do prefer 1 and 2, since passing the data through the intent doesn't provide the luxury of shared data. RxJava (+ MVP) also provides many other benefits, but it's not the topic of your question.
I have to send and receive objects between a smartphone and a remote desktop (running Java) via Bluetooth. The smartphone and desktop both share a series of classes that constitutes the application data model.
I need to implement the Parcelable interface on the smartphone app so that when receiving an object from the desktop app, I can send it back to the main activity via a Handler. Unfortunately, this wouldn't work because it would make the classes unusable on the desktop app.
So my question is : Can I send the objects without the Parcelable interface implemented to the desktop app and then make them Parcelable through a generic class when receiving them.
Something like that :
Object orgObject = new Object();
//Make an object Parcelable
ObjectParcelable objPble = GenericClass.makeParcelable(orgObject);
//Remove the Parcelable implementation
orgObject = GenericClass.undoParcelable(objPble);
My preferred solution for this problem is serializing the object to JSON (for example, using the Gson library) and sending it as a string. Then on the other side you can deserialize the JSON to an object using your preferred library.
You need to convert the object that you would like to send to some intermediate format like json or xml for instance. Then you can send this serialized message from the android side and deserialize it on the java side, and vice versa. You can use for that a library that works the same way on android and java, for instance https://github.com/google/gson. In this way you can use same java class files, for your model in both applications.
To pass data from an Activity to a Fragment, naturally, I think of using a Bundle. The problem in my case is that the Object I need to pass is a Google Cloud Endpoint message, which is neither Parcelable nor Serializable. So how might I pass the data?
For clarity, a Google Cloud Endpoint message is a POJO that is used to pass data to and from endpoint methods. I assume they would be Serializable, but to my surprise they aren't.
You can:
Subclass and implement Serializable or Parcelable on that class
Or use any other strategy to pass data inside of the app:
Singleton class holding any memory cache you may use
If the fragment is inside of the activity you can access the fragment from the activity and pass the variable in
In the worst of cases you can always use SharedPreferences or any kind of disk persistence
This question already has answers here:
What is an Intent in Android?
(14 answers)
Closed 9 years ago.
I still don't understand what is so special about Intents. Why not just use a new thread or just call the function? I think I got the whole idea about intents wrong. A simple code showing why Intents are better or when are needed would be great!
Intents are get widely used in android to switch from one activity to other . it is good practice to use intents . Using intents we can pass/send values from one activity to another. So it can be used as value passing mechanism. Also its syntax is very simple.so why to think about threads ?
Intents are asynchronous messages which allow application components to request functionality from other Android components. Intents allow you to interact with components from the own and other applications. For example an activity can start an external activity for taking a picture.
Intents are objects of the android.content.Intent type. Your code can send them to the Android system defining the components you are targeting. For example via the startActivity() method you can define that the intent should be used to start an activity.
An intent can contain data via a Bundle. This data can be used by the receiving component.
To start an activity use the method startActivity(intent). This method is defined on the Context object which Activity extends.
The following code demonstrates how you can start another activity via an intent.
# Start the activity connect to the
# specified class
Intent i = new Intent(this, ActivityTwo.class);
startActivity(i);
Why not just use a new thread or just call the function?
No matter what Thread you use, there would still need to be a mechanism to direct the message which is what an Intent does. It is a way to send a message. Now, it needs to be called on the UI Thread or have an appropriate Context passed because it needs this to send the message. Call what function? You are. It calls a constructor of the Intent class.
A simple code showing why Intents are better or when are needed would be great!
I don't have a simple code to compare to because I'm not sure what you want to see. No one is saying that it is better than something else. As to why Intents are used opposed to something else? I don't know...you would have to ask the developers of the Android platform. That is what they decided to use.
When they are needed is when you want to pass a message from one Activity to another or from one application to another. From the docs
An intent is an abstract description of an operation to be performed
I said "message" but the docs say "description of an operation to be performed" (I guess can mean the same thing). You can use them to start an Activity, pass data between Activities, and more such as telling the OS what to do at boot time. Why is it better? Better than what? That is what the developers decided to use so I guess you would have to ask them but maybe they didn't think it was better rather different.
while I don't have an example, Intents encourage coupling components loosely.
It negates the necessity of you building your own Observer design patterns and enables Inter/Intra-Application communication.