Suppose we have a list of complex objects (primitives and other objects inside) requested from a server to show them inside a RecycleView. In adapter we need only some data from each object, let's say 70%.
I get from server list with full data objects, and each object implements Parcelable so when I select a item I pass object via intent to MyDetailsActivity like so:
Intent intent = new Intent(context, MyDetailsActivity.class);
intent.putExtra("foo", myComplexObject);
startActivity(intent);
This is working as expected but on some low memory devices I get out of memory errors. So my question is how to achieve this type of data flow?
One possible solution is to implement get/set for MyObj in Applicattion class, and pass it like so but I'n not sure if it's stable.
And of course I can pass just an id from MyObject and do another request call inside DetailsActivity's onCreate(), but this requires user to wait some more seconds to load data.
Any advices or references are apreciated
As you have experienced, sending data through the bundle/intent extras has its memory limits.
Your options are to either keep those objects in memory and access them via some static/singleton instance or to do the data query from your server in the desired activity that will show them in your list.
Another viable options is to store the data in a database for ex and read it once its required but this ofcourse depends on your current architecture... you can checkout Realm, Room, GreenDao database options etc...
Second approach is more suitable for mobile applications since you only load data in list via API which is visible inside the recycler view, you can pass that data to activity and then in activity load the remaining data from another call for that specific item.
I'm assuming that each object of the data coming from the server is not of same size, leading to out of memory on some but not all the objects. So the better approach is to also modify server apt (if possible) to send only info which is required for the list in your call's response and have separate resource url to access full information for that object.
This may result in a minimal delay but it will not cause unexpected out of memory errors which is a big let down for the end user.
You can actually use Application class for this purpose, to make it even better
Set the data in Application class when you intend to pass
Retrieve the data at destination into Local variable from Application
After retrieving data into local variable, set object in Application to null
Using above approach will make sure your objects memory is released as soon you consumed it without holding it all the time throughout Application Lifecycle
Related
Which one of two ways below has better performance for transferring data between activities?
Activity1: putExtra("id" , customerId)
Activity2: Select on the table and fill Customer object
Activity1: putExtra("customer", customer)
Activity2: Customer customer = (Customer)getIntent().getExtras().getSerialaizable("customer");
I mean send a unique item (like id) to the next activity and then select it from data base OR send the whole object to the next activity and cast it?
Obviously first way. You just send the ID of the object and then read it from the database in second Activity. The other way involves serialization/deserialization which costs CPU-cycles. Even using Parcelable will still use significant CPU-cycles.
On the other hand, I doubt that you would notice any performance penalties unless you are doing this for a bazillion objects. Do whatever is more straightforward and easier to understand/maintain.
Serializable is not recommended in android, check parcelable it's faster.
Serialization vs DB depends on object complicity, only profiling can show the picture, but for a one object it's neglectable.
The fastest way would be to store object in memory and share through singleton.
Just like it says on the tin. I have a decent sized object, consisting of about 20 variables, some of which are themselves android objects (Calendar, Uri). An arbitrary number of these objects are stored in a database.
I need to pass an individual object by intent to a broadcast receiver. When I create the intent I already have the entire object as a local variable and would not be querying the database. Is it more efficient to pass the entire object as a parcel, or to pass the database id and pull the object from the db in my onReceive method?
I suspect the former, but until yesterday I was doing the latter because I was too lazy to implement parcelable. I did, but now I'm second guessing myself.
P.S. I'm no CS major. In this case I define most efficient to mean least impact on user experience.
If the object in question is small (under 1MB), then going the Parcelable route should be more efficient. Basically, you avoid the disk I/O (and the accompanying complexity of trying to do that on a background thread when triggered by a broadcast).
I am building an app which allows the user to define multiple objects of a specific type, lets call them "Person"'s. The "Person" object is defined as such:
class Person {
public String name;
public int age;
}
These "Person" objects will be serialised and stored within the app, either in SharedPreferences or via a Cloud storage mechanism. This can be considered handled and working.
My problem is that I need an editor interface to allow the user to change the "name" and "age" of any particular "Person" instance in their collection. In order to make my UI feel as much like stock as possible, I would like my editor interface to resemble the "Preference" interface which Android implements. As such I need a way to make a "PreferenceActivity" load and save it's preferences from/to a POJO.
The reason I am looking to do this is so that I have a UI that feels like something the user is used to using. My other choice is to mimic the style and create all the handling code myself, which will take a lot of time.
I imagined the process would be to override the "load" and "save" functions of a "PreferenceActivity" to pull/push the values from a POJO provided "onCreate" via an "Intent" - and the return this POJO as an activity result to the caller.
Is this achievable?
What is the purpose of having it this way? I fail to see why this would be useful nor how it would be feasible with regards to the reference of the pojo containing the data. If it was possible then the saving object would most likely be a generic key-object map, where you would need to extract the data from, which is exactly how the Preferences already work.
If the point of this is just to have the information in a Person object why not just make a method that creates one based on the saved preferences.
----- Additions
If you add a static/singleton data handler(repository) in the App that will contain all the persons while the App is executing, and that it has some kind of identifier for each person. Then you can pass the ID in the intent to the PreferenceActivity which will in turn fetch the person object from the data handler and fill in the values of the PreferenceActivity based on it.
Add another Preference to the PreferenceActivity named "Save" or similar, which you resolve and bind in the activity. When clicked this will fetch the currently entered information (which will be saved in the SharedPreferences) and create a Person instance out of it. It should then pass this object to the data handler which will add it (or update it if the ID is already there) to the repository of Persons. At this time you should probably consider serializing the whole repository and save it, one easy way is just to JSON it all and put it into the SharedPreferences. Don't forget that you need to load this data the first time you access the data handler so that the previously saved persons are accessible.
I would also recommend you create Interfaces for the data handling action in case you want to add new or replace the implementation to for example database operations instead.
This way you can use the PreferenceActivity for add/editing Persons. Even though I would prefer create your own UI for it.
The application passes large number of objects (about 150 objects after parsing JSON format) via intent.putExtra();
Among them are serialized objects.
And the process of opening a new activity takes about 2 seconds...
Is there a way to speed up this process?
If you just want to pass data from one activity to another you can just use a static variable that is accessible from both activities. This eliminates the need to serialize and deserialize all the objects. Example:
public class Globals {
public static List<MyObject> myObjects;
}
In one activity you can set the data you want to pass in Globals.myObjects and the receiving activity can get it from there.
Be aware that this mechanism does have some drawbacks (like when Android kills your process and restarts it later). However, this can be the least troublesome way to simply hand a lot of objects from one activity to another.
One suggestion could be:
Use parceable where you are using serializable
Another suggestion could be:
Use something else to save/restore the data. e.g. a database
I think using a Singleton class for sharing large amount of temporary data between activities is a great way to go. Keeps it really quick and simple.
Although it can be done through Android Parcelable but it has storage limitation which can cause this error "!!! FAILED BINDER TRANSACTION !!!"
Suppose you want to start a new activity and pass it some data from the current activity. If the data is of a primitive type you could simply use an intent and add extras, but how would you do this for more complex data structures like arraylists or objects?
You have a few options:
You could wrap the more complex structure in a class that implements the Parcelable interface, which can be stored in an extra
You could wrap the more complex structure in a class that implements the Serializable interface, which can be stored in an extra
You use static data members to pass stuff around, since they are all in the same process
You use external storage (file, database, SharedPreferences)
As the person who just posted noted, use a common component, such as a custom Application or a local Service
What you do not want to do is pass big stuff via extras. For example, if you are creating an application that grabs pictures off the camera, you do not want to pass those in extras -- use a static data member (icky as that sounds). Intents are designed to work cross-process, which means there is some amount of data copying that goes on, which you want to avoid when it is not necessary for big stuff.
One option I am aware of is storing the data you are using in an Application object which all your activities can retrieve from context.
I have also heard of using Google Protocol Buffer to achieve a higher performing solution