Im building an android app and in the startup activity i parse a pretty big json file (3.3 mb) into custom objects, or when there was no update i retrieve it from a serialized bytearray. Im dealing with one object with a list of about 500 objects with subobjects, lists etc.
Now i need this data, or some of it in my other activities. What is the best solution for this?
It seemed a lot of data processing to serialize and deserialize using intent.putExtra or using parceable everytime you start a new activity. Is this processing less than i think or is there a way to use your parsing class and don't destroy it so you can use something like
Myclass.get(nrIneed).Mysubclass.getsomestring
?
This is how i did it when using data for logging or something in my parsing activity.
You can use Application class to store this data and you can use it across all the Activity
public class BusinessClass extends Application
{
public ParsedData parsedData = new ParsedData();
}
Then call it in any activity using following code
BusinessClass appState = ((BusinessClass)getApplicationContext());
appState.parsedData.getData();
For more info
http://developer.android.com/reference/android/app/Application.html
You SHOULD NOT use Parcelable for objects which may consume memory more than about 1MB. Otherwise the parsing will fail (at least as per API level 8).
However, in your case, I would recommend you to save/organize the parsed data into SQLite and query it from other activities. This will help your app to eat less memory :)
You may also create a static reference to your object, but since its huge in size, I wouldn't recommend you, because then your app will become an appealing target for android VM to kill - when running under low memory circumstances.
I think you shouldn't use your data as a big Json file. At the first launch you should save your data in a database then only use this db when you need to Create/Retrieve/Update/Delete.
If you really want to use your JSON file, then you should make it static (in your application singleton for example).
Hope this will help you
Related
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
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 !!!"
Question:
Is it possible to share natively allocated data across multiple threads on Android?
Example:
In the onCreate() function, I allocate a struct on the heap using native code and return a pointer to that data.
Later on in the application, I would like to use that data in a different thread, in my case a GLThread used to render the data out...
Is this possible? If so, what would be the best way to go about this?
I dont know if I understand the problem, you want to have some kinda share data object?
In my case I use something like this:
Create new class, which extends from application and there you can keep the variable with public getter and setter.
In any of your intent you can just call for this class:
DataHolder data = (DataHolder) getApplication();
Don't foget to add this class to manifet as application.
I need to pass a List of my objects between activities. I do not want to use parcelable or serialize the data each time. I also do not want to save it in a local file or database. That probably leaves me with using static objects.
Lets say I to use ListA between activities Activity1 to Activity2. I ca
Approach1: Create a static ListA in one of those activities and do all my stuff of that static ListA.
Approach2: Create a static list in another class which I use just for storing this List and doing all my stuff on this list. But this means that this stays as long as my process is running and I have to manually set it to null when I do not need it.
Approach3. I am extending the above class to implement it using a static HashMap.
I have two methods one to store the list in a static HashMap using a unique key and another method to retrieve the list and remove it each time data is retrieved so that the List is no longer present in the static HashMap. So we essentially have to pass only the random key generated to store data between activities which I can pass as an extra using Intents.
Will there be any issues when I use any of the above approaches and which will be the best approach.
I'd consider creating an Application object and using it like a singleton to access your data. I've described the approach here: http://chrisrisner.com/31-Days-of-Android--Day-7%E2%80%93Sharing-Data-Between-Activities. Some people don't seem to like using the Application object in this manner but it makes more sense to me than putting a static object on an Activity.
Uggg statics! Man I wish all developers understood global variables are bad and how they make your program more brittle and your life hell. We only been talking about how bad they are for 30+ years, but unfortunately no one figures this out until they've utterly hung themselves on them.
First I'll say serializing your data is fast. There are great tools out there that will serialize your objects quickly that you can use I prefer http://flexjson.sourceforge.net for this.
So if you are just outright opposed to this you can pass this object through the Application by subclassing it, declaring your implementation in your Android Manifest, and each activity has access to the Application instance:
public class MyActivity extends Activity {
public void onCreate( Bundle bundle ) {
MyApplication application = (MyApplication)getApplication();
Object anInstanceFromAnotherActivity = application.getSomeInput();
}
}
The downside to this is when your application is reclaimed if the user returns to your application the memory is gone, and you can't get that input you might need of your screen. Android framework is trying to make you serializing things in the bundles because if it decides to destroy your application you can always rebuild yourself from the bundle. Now there are short cuts you can take like redirecting people to start over if the Application has been reclaimed, but those depend upon your program and what its doing if they make sense.
That's where using serialization wins out over all other forms of persistence (parcelables, files, databases) because it can be done in one line of code.
i have a basic function which requires serializing in my android app. The user will add some values to an ArrayList and i want to serialize it to avoid using a database for this little option and of course TO LEARN how to serialize (i'm a begginer) because it seems useful. Anyways the user save something in the arraylist, the program shuts down, the program starts up again and the user is able to see the saved data. How can i implement this? Can you provide some code snippet or a useful link?
Thanks a lot!!
You can do this by custom bean class and implement Serializable to that
so now when you create ArrayList<E> of that class it is Serializable.
Example:
Class dataBean implements Serializable
{
public String name;
}
ArrayList<dataBean> dataBeanArrayList = new ArrayList();
So dataBeanArrayList is now Serializable and you can also pass this between Intent.
I suggest using flexjson to serialize the data to a file. Then you can read that back using that library. This has several advantages over serialization which is being able to load your stream back into potential differing versions of your objects. Using ObjectInputStream you have to be very careful, and quite frankly I've never seen it work all that well.
http://flexjson.sourceforge.net
Here is a blog post how to do that:
http://wrongnotes.blogspot.com/2010/09/flexjson-meet-android.html