My app initially makes a request for a list of objects from a server. These objects are currently kept in memory as an ArrayList<MyObject>. However, I want these objects to be passed through multiple activities before the user terminates the flow by pressing a button. I could make the ArrayList serializable and pass it through Intent extras. But I could also store MyObject(s) in a SQLite database and access/modify them in any Activity without having to go though intents. I was wondering what the norm is to accomplish this.
EDIT: forgot to mention that all the values would be deleted once the user terminates the flow.
SQLite is not the best way to go in your case since you don't need the data to be persistent after you close the app. It will just slow your app having to store and retrieve all entries on every activity transition. You can do one of the following instead:
Pass Serializable the way you described. Might be slower than the other alternatives though
Make MyObject implement Parcelable and use [intent.putParcelableArrayListExtra()](https://developer.android.com/reference/android/content/Intent.html#putParcelableArrayListExtra(java.lang.String, java.util.ArrayList))
Extend Application and load the list from the network in your Application.onCreate() and call getList() from activities that need it. That way you load it once and you don't need to pass it between different activities.
Related
I am trying to save an instance of StatusBarNotification, so that i could show the notification later to the user. I noticed that StatusBarNotifcation is not Serializable but Parcelable. Is there any way to store the exact instance state in the database so that even if user turns of his phone, the instance object is stored.
I know its not the best practice to store the Parcelable object in database. But I need to do it.
If there is any way i could get the byte array of the instance, I am open for suggetions.
EDIT
I found out today that, if I turn off my android phone with some un-attended notification, when I restart my phone I am still able to see the same notifications. That being said, android is somehow saving the same instance of notification.
Now my question is, how?? And if android does why can't us.
Is there any way to store the exact instance state in the database so that even if user turns of his phone, the instance object is stored.
No. In particular, not only do you have no way of persisting the PendingIntents associated with the Notification, but you have no way of recreating them with all the security rules intact. A PendingIntent is tied closely to the app that creates it; you are not the app that created those PendingIntents originally.
I think you cannot save the parcelable object of notification in the database (also not a good practice).
I'm creating simple application that uses JSON format and SQLite database to store parsed information into that. I'm aiming to support both normal devices and tablets, so I'm using Android Fragment API.
My problem is that I'm not sure where I should store the reference to my database, at this moment I have main activity that incorporates two fragments - list fragment and details fragment (both of them are adjusted for tablets and normal phones).
I need to fill mentioned list with information from database and in future I want to implement additional search function so reference to database must be shared by almost all fragments/activities.
In addition I have special class(Util) that stores HTTP object and JSON parser. Is it good idea to add static database reference to that class and create new instance of it in seperate thread (initialization block) ? Or I should consider create it in MainActivitity and create getter and setter ? My MainActivity implements appropriate interfaces from list fragment so I'd need to cast it.
I need to access a few of my custom objects in different activities of my application. For this purpose and for the sake of accessibility I have been using static properties for moving data from an activity to another.
For example I have the following class:
public class TrackItem {
public String title, imageUrl, mediaUrl, type, artist, desc;
public static TrackItem track;
}
And for starting an activity:
TrackItem.track = items.get(i); // 'items' is an arraylist defined elsewhere
Intent trackActivity = new Intent(c, TrackActivity.class);
startActivity(trackActivity);
And now inside the TrackActivity I can easily access TrackItem.track and use it's properties.
I just need to know if I'm making a mistake or not? Is there any better way to do this?
The android way of dealing with that problem is to make your class
Parcelable
and pass it with the intent from one activity to another.
If you are initializing your static variables in an activity be aware of loosing data, because in android activity can be destroyed at any point after its state changed to pause. Moreover, your static variables can be erased if the entire application is killed by the system, that is happening rather frequently. Then you'll get the
NullPointerException
trying to access your data.
If you really want to use static members handle their initialization in the
Application
class constructor, so they will be recreated on the start of your application, being killed.
But in general it is not a good practice in android.
I would say it is OK in certain cases, but there might be other more suitable solutions.
You could have a central data store class that uses the singleton principle and therefore would be accessible from everywhere. You would add the item id to the Intent for the new Activity. Then, with the id, you could get the item from the data store.
You could also make the item serializable and just add it to the Intent.
One thing to keep in mind when using static members is that it could lead to a memory leak. Static members are related to the class and are therefore only garbage collected if you either set them to null, or the whole app gets killed and the classloader unloads this specific class.
In general, this is an unsafe practice because it is difficult to keep track of who is manipulating its data. It is much safer to use static variables for bookkeeping information, such as an ID which you can use to go look up the appropriate TrackItem (e.g. in an SQLite database), which is its own object and does not have the chance of something else editing it when it shouldn't be. It terms of OOP, using static variables as shared data breaks encapsulation.
If you are looking to send data around the app, it would be much better to do so either with intents, as others are saying, or with SharedPreferences. Both have the advantage that you are dealing with only one instance of the object at any given time, SharedPreferences have the added advantage of keeping the data around after the app has been killed, so that users can resume with the same track that was playing when they closed the app. And both of these are safer than using static members as shared data fields.
Currently im storing all of my users information and there friends information inside a class i have created called userInfoCore that extends Application so i can store the values in the Context. When my app crashes it gets rid of al those values and my users are forced to relogin, so i would like to store them in SharedPreferences to be grabbed again in the onCreate of my MainActivity.
I know how to store them, thats not the issue. The issue is i dont want to overcrowd my code with repetitive code and put the storing methods in all the onDestroy's of all my Activities, and i cant #Override onDestroy in my userInfoCore class because its not an Activity i imagine?
Some insite would be great. Thank!
EDIT:
Ive found out that this line in the android manifest is causing my Application Context data to be destroyed even when the user presses the home screen. android:launchMode="singleInstance"
My thoughts are YES i could store them in the onPause or do what #CommonsWare suggested. However like i said, i dont want to have to do all of that. If i can find the root of the cause of the issue... which i have. (The singleInstance in manifest) then i would be much happier.
Some insite would be great.
Update your persistent store when the data changes. A custom Application subclass, like any singleton, should only be treated as a cache or other transient spot for data. If you care about the values, persist them, at the point when the data is changed.
This is a good argument for using the Model-View-Presenter (or Model-View-Controller) pattern. By separating your Model (domain data and procedures) from your View and Presenter (Layout and Activity respectively) you only have to write the Store logic once.
Then you have two choices: either do as #CommonsWare suggests, have the model write itself whenever it changes, or add a simple call in each Application's onPause (onDestroy is too late! It may never get called.) to the model to tell it to save itself.
Note: the model can accept a context as a construction parameter for use in finding a shared preferences, or it can create it's own named preferences using the PreferenceManager
I have a Network Client class that is receiving a large binary block and parsing it into a usable Java object. The Network Client is on a separate thread from the app's View. What is the best way to make this object available to the View? I've come up with the following solutions, but I feel like none of them are the correct one:
Create the object in the Network Client and let the View access it directly
I would send a small message in a Handler telling the View that the data has been updated
Con: requires that I synchronize the object between the threads to ensure that the Network Client doesn't replace the object while the View is accessing it
Serialize (Parcel?) the object in the Network Client and send it through a Handler to the View
Pro: there are no questions of ownership of the data
Con: would probably be a huge performance drain on the app
Create a reference to the object and pass that to the View
I come from a C++ background, and I'm not sure if this is even possible in Java. I C++, I could just send the View a pointer to the object and let it take care of it. That seems like something Java wouldn't let me do. Is this feasible?
Are any of these solutions advisable, or should I approach the problem in a completely different way?
If you don't want to keep downloading when the activity is in the background, then use non-blocking IO, not threads.
If you do want to keep downloading when the activity is in the background, you probably want to use a service. You can make the object Parcelable or so; I think the underlying service implementation passes pointers around if your activity and service are within the same process (I think they are by default, but ICBW).
If the object is really big and you don't feel comfortable returning it with a get method, maybe you could put its contents into an SQLite database and optionally expose it as a ContentProvider. You could also send an Intent and either cause the View to then go and grab the payload or attach it to the Intent.
Look at the application class subclassing this class and referencing this within your manifest will enable you to store the reference to the service/download controller at a central position that will be available in every activity of your app. This enables you to keep the data in memory and reduce the need of recreating the big object if you need it in more places then just one activity.
For the download you can use a local service that communicates with your activity through a binder object. Keep in mind that a service is not a thread. If you want have the download running in the background you need to create a thread in the oncreate method of your service.
Also keep in mind that it is good practice to have an annotation show the user that a service is doing something and let him access the service and cancel it or view it status.