I am making an Android app using the Parse SDK. What I am struggling with is the flow of creating a post. Currently, in my main activity, a user selects the type of post (photo, video, etc.) takes a photo/video and goes to the next activity called NewActivity. In this activity, a user can review the photo/video and edit the privacy or place of the post. to change the privacy or place launches a new activity for each.
The main problem I'm having is retaining and passing this Post object between the activities.
My first (bad) solution was just to pass the data with the intent in a Bundle, but this soon got very messy as I really needed to pass a Post object between the activities. I switched from that solution to using a Singleton class called, DataHolder.
In each activity, I call DataHolder.getInstance() and when the create post button is clicked, I create a new Post object by executing: DataHolder.getInstance().setPost(new Post()). In the following activities, as the user enters more information about a post, I set the Post's properties.
This was all working well until I ran into this issue. When I would return to my app (presumably it had been killed) I would get a NullPointerException because the Post object was null. I was looking through the Android docs on passing data between activites/services and needed a little help.
Should I be using the Singleton class pattern here? What would be the most efficient and easiest way to pass this Post object between the activities? Should I use an application singleton? I would use Parcelable or Serializable, but the Postobject is a ParseObject so this is not an option. Should I avoid passing the data altogether by using Fragments for the privacy and place activities (though they have different screens and different action bars)? Should I use startActivityForResult for the privacy and place activities?
You should consider that the app could be killed at any moment for any reason and be prepared for this. You could use something like a session object to communicate between activities. You can save it / load it as often as needed so you will not run the risk of loosing data. If you cannot serialize the actual object (eg the ParseObject) you could serialize the parts needed in order to reconstruct it (ie save the image in a temp folder and load it on demand).
Related
I'm new to Android development and was unable to find how to pass values to an activity that is not the next screen that the user will see. If I have activities in this order: 1>2>3 connected by buttons, how do I pass a value from 1 to 3? I'm only familiar with using intents on button clicks, which would require me to pass the value to screen 2 and then to screen 3.
Thanks
There are several ways to do that:
1) From Activity1 you pass data though Intent. In Activity2 you retrieve data and pass it within new Intent to Acitivity3.
2) Save data in SharedPreferences in Activity1 and retrieve them in Activity3.
3) Save data in SQLite database which is default for Android. This is a good option if you need to save/query data not once, but many times.
4) Save in Google Cloud or use other services.
You can see here a full bunch of store options in Android. Without performing those actions, storing/retrieving data though the Intent is the only one way.
Note: Make a static variables is such a bad practice, unless it is just constant values or other utilities.
If the chain pass becomes too complicated then you should persist it. My suggestion is using Preferences to save the value. Later you do an existence check in the retrieving Activity, load it, and if needed clear it. This is the method commonly used when storing app Settings values.
If your values become more complicated in structure and more numerous then you'd need to consider database.
My problem seemed simple to me, but apparently it isn't.
I got a core class that is able to calculate a complex result depending on parameters entered by a user. Up to now I showed the result as a ListView and for the detail view, I used a sliding panel - so everything is neat within one activity A.
But now, I wanted to get rid of the sliding design and "simply" use a master/detail flow so I could show two fragments next to each other on tablets and separately on a mobile phone.
Well, I did not want to redesign the whole app for that, but basically: how do I get the detail information to my different activity B???
I know that through an Intent I can only send Parcelable (or serializable) data, but that is far to complex for essentially int-array-type of data! All the converting to and re-constructing from the Intent - that is just a pain!
Of course, I also do not need a database or similar complicated stuff - no SharedPrefs, please, that is all at least as complex as implementing the Parcelable!
Basically, I thought of two approaches, but they all ... stink ... kind of:
a) store the calculated data within the application class - problem: the app might get destroyed and restarted just for re-displaying activity B. Then there wouldn't be anything left in the app object!
b) implement a content provider that does the calculation and caching the result there. Hmm. The cursor again is way to complex to transfer the simple result. And: for how long should I cache the result in the ContentProvider?
I feel this is all a mess. :-(
Any ideas?
The Intent approach is by far the simplest one.
Talking about a Master/Detail flow, usually that means passing one id, this is few information and easily reconstructed from A to B (activity).
Don't use A for exactly the reason you mentioned, and B wow! too much work =)
I really think either use an Intent or use shared Prefs they are by far the least code demanding options.
Have you been able to create the behavior of the app getting destroyed and everything being deleted? I've been developing an app doing some things along the same lines and I have just been using public static variables to store things in the activity that they are created in. That way they are accessible from other activities. Not necessarily the most elegant way of doing things but it's working for me just fine.
oh man its not mess:)
did you aware of Design patterns if yes then you can use singleton pattern where you can store data for your next activity
public class mySingleton
{
mySingleton instance;
yourvariable1;
yourvariable2;
yourvariable3;
yourobject1;
yourobject2;
public static mySingleton getSingletonInstance()
{
if(instance==null)
{
instance=new mySingleton();
}
return instance;
}
}
by this you can save your data till your any activity is running or you may say untill your application is in system memory
but if you want to close application and persist data then make a background service there you can save data your applications activities will destroy but the service will contain the variables and data
hope it will solve your problem
I'm on the situation where I have to share variables between activities... but I have one doubt. Which is better: Parcelable object or set it on a custom Application object.
When something is just going to be used in next activity I just pass it as a Parcelable object, and when it is going to be used in more than one activity, I put it on Application context.
What do you think? Is it right? Which is better in performance?
Thanks!
I think your approach is completely valid.
If it is something like a user object that is accessed in every Activity store it in a custom Application object, but be sure to have a way to recreate the object if the application object gets destroyed while the app is in background.
If it is something like a path or a choice the user made that determines how the next activity works send it with the Intent.
There are also some classes that are not easy to put in an Intent. I have an ImageCache that is attached to the application class that allows to keep images like a user profil image in memory between activity changes without the need to decode the bitmap multiple times. If they are designed in a way that they don't fill up all available memory those are also a good fit for a custom app class.
I recommend sharing data between activies with extras. If it's a own class, it must implement Serializible.
If you are feeling lazy, go with Application's singleton pattern.
But, if you want to code smarter, go with Parcelable.
I have a similar issue with this one:
Android: Multiple activity instances launched by same intent. Bring one uniquely to foreground?
I need to create a stack of activities, all created by using the same class: it is a class defining a news list, only there needs to be multiple children activities that are also news lists, but from different categories. (I do need to have these activities in a stack)
The trouble is I need to change data on each of these activities after they are shown, but I can't find a way to access each one of these activities separately, since they are all using the same class, so if I used static methods, I would change the data on all these activities at the same time. Ideally, there could be a way to use references of each activity, so that I can access methods on each one separately, but I don't think there is a way of doing this.
I might as well pass parameter IDs when starting each activity, and instantiate objects at the same time, for each activity, and using these IDs later access the respective objects' methods...
Edit to clarify: Let me use an example to what I am trying to achieve. I have an A class and I am using this same class to instantiate multiple activities, in a stack. After the creation of these activities, I need to alter data, say, on one of these activities statically, so by calling A.alterData(); , but not when the activities are created, so there is no way of doing this by starting the activities with different data.. Since there are multiple instances of this class, if I do so, this will result on altering the data on all these activities, that are using the A class. Would I be able to somehow use objects and methods to these objects to alter data on different activities that are using the same class?
any other ideas?
You could use an ActivityGroup. It basically holds a list of activities and you need to control the navigation around them. It sounds like it suits your situation. There are many examples of them that can be found through google.
How I would approach changing the data on the other screens is by using shared preferences. You can store whatever data you need in there, and then (through your activity group) when you change screen, the data is refreshed. This is faster and a little more efficient than restarting the intent every time.
Another way is to change the data in the background without the user noticing. This can be done because an Activity group loads all of the Activity it holds and they are always there in the background, running, unless the developer states otherwise.
You could grab a a hold of the appropriate instance of the class you want to change the data on and then just change it.
Does any of this make sense?
I can elaborate more if needed.
I would supply the parameters to each activity, such as:
intent.putExtra("category", categoryId);
That way you aren't managing too much global state.
About changing the data - if you are talking about refreshing the data from its original source, then you should probably be doing this in the onResume() method of the Activity. Check out the Activity Lifecycle.
This has a few benefits:
you will have access to all of the context of that Activity
you won't have to do something nasty like access another Activity's data
you won't waste time refreshing data the user isn't looking at
Even if you have to make updates to the data, there are ways to make sure each Activity "minds its own business".
I have read some question here but I didn't find a solution. I have read about Parcelable, Intents, and sharing specific data within Activities from the android dev docs (both dev guide and reference).
Here's the scenario:
I have one ListActivity that fills in an object parsing an xml file, it shows a list of values, and when clicked I want to return the object that represents the item clicked to the activity that has called it, for then, call another activity with this object.
I read on how to implement Parcelable but seems not being the way. Implementing Parcelable receives a Parcel for the constructor and then reads the values from it (or at least that was what I understood). This makes no sense for me and I can't see how to implement basing on that issue. I build the object parsing the xml file, not having a Parcel.
I appreciate some clarifications on this, regards.
I believe you have three options here:
Pass some arbitrary 'id' of the object to the new activity in the intent extras, which obtains the object in the same way as the first activity. This I would recommend as it is in harmony with the way Android is designed to work.
Serialize the object using Java Serializable, then put it into the intent as an extra.
Have the object be a JSONObject and send it as a string in the intent extras.
That depends on whether the activities belong to the same process or different ones...if it is the same process then the answer is Within an application what is the best way to pass custom objects between activities? but if they belong to different processes then you are better of implementing parcelable.