Working with same data in three activities - android

I'm not very experienced in android specific components, so I just can't get where I need to look.
I have three activities:
1st gets info about some groups of objects, user selects some of this groups and activity needs to star next activity
2nd activity shows all objects from groups, that user selected at previous activity, here user can deselect some selected objects and then activity starts 3d activity
3d activity allows user to do something with selected objects
My solution is make some singleton model, that let activities get and save information about objects,
but i suppose, that android has some special components to provide data between activities
Help me to find this components^ please

It depends on the type of data that you want to share:
Primitive Data Types
To share primitive data between Activities/Services in an application, use Intent.putExtras(). For passing primitive data that needs to persist use the Preferences storage mechanism.
Non-Persistent Objects
For sharing complex non-persistent user-defined objects for short duration, the following approaches are recommended:
The android.app.Application class
The android.app.Application is a base class for those who need to maintain global application state. It can be accessed via getApplication() from any Activity or Service. It has a couple of life-cycle methods and will be instantiated by Android automatically if your register it in AndroidManifest.xml.
A public static field/method
An alternate way to make data accessible across Activities/Services is to use public static fields and/or methods. You can access these static fields from any other class in your application. To share an object, the activity which creates your object sets a static field to point to this object and any other activity that wants to use this object just accesses this static field.
A HashMap of WeakReferences to Objects
You can also use a HashMap of WeakReferences to Objects with Long keys. When an activity wants to pass an object to another activity, it simply puts the object in the map and sends the key (which is a unique Long based on a counter or time stamp) to the recipient activity via intent extras. The recipient activity retrieves the object using this key.
A Singleton class
There are advantages to using a static Singleton, such as you can refer to them without casting getApplication() to an application-specific class, or going to the trouble of hanging an interface on all your Application subclasses so that your various modules can refer to that interface instead.
But, the life cycle of a static is not well under your control; so to abide by the life-cycle model, the application class should initiate and tear down these static objects in the onCreate() and onTerminate() methods of the Application Class
Persistent Objects
Even while an application appears to continue running, the system may choose to kill its process and restart it later. If you have data that you need to persist from one activity invocation to the next, you need to represent that data as state that gets saved by an activity when it is informed that it might go away.
For sharing complex persistent user-defined objects, the following approaches are recommended:
Application Preferences
Files
contentProviders
SQLite DB
If the shared data needs to be retained across points where the application process can be killed, then place that data in persistent storage like Application Preferences, SQLite DB, Files or ContentProviders.

yes, you can send data between activities using Intents. Using the putExtra() function for that. If you want to pass your own objects, you need to implement Parcalable class.

There is no problem with using a singleton to share information between your Activities, especially if you need this data to be consistent throughout your whole app.
Alternatively you could use an Intent to pass data between Activities - putExtra().

Yes it does:
http://www.remwebdevelopment.com/dev/a33/Passing-Bundles-Around-Activities.html
Basically you can either send a Bundle or just use putExtra function for that.

try this way please
Intent i = new Intent(this, YourTragetedActivity.class);
i.putExtra("value1", "test1");
i.putExtra("value2", "test2");
startActivity(i);
//// On Your TragetedActivity
getIntent().getStringExtra("value1")
getIntent().getStringExtra("value2")

Related

Keeping reference of an object for a task's lifetime

I am looking for a way to keep reference of an object/instance that's a member object of a service. I know in case of Activities, we can save it by the provided onSaveInstance method. However, I couldn't find any similar way for a service.
I can use static object but it's unsafe as there is no guaranty, if the reference would be valid the next time, the service is created.
Another possible way would be, I store all the data on storage & later on when the service is created again, I can read the data from storage. Then traverse through information/data provided by the another class & find the relevant reference for the info read from the storage, which I think is very expensive interms of execution time.
So I am looking for a way to get rid of all this process & keep a strong reference (of the object in service) in the memory as long as the task/app is running.
Regards
You can use application class to persist data as
public class MyApplication extends Application
{
public MyDataClass data = new MyDataClass();
}
Then call it in any activity/service by:
MyApplication appState = ((MyApplication)this.getApplication());
appState.data.useAGetterOrSetterHere(); // Do whatever you need to with the data here.
In your manifest mention it as follows::
<application android:name="yourpkgname.MyApplication"/>
More info are like
Application object is an object whose lifecycle is same as our Application.
When Application starts this object is created automatically by Android Framework.
When you want to share data between more than one activities of your application or you want to retain something at application level.In that scenario you can use Application object as a global store for your application.

Saving Arraylist<Hashmap> for displaying after rotation

I can I retain ArrayList<HashMap<String, String>> in bundle?
I want to display ListView immediately after rotating the screen.
You dont have to save it in the Bundle. In fact, that seems like a lot of info to store in a Bundle.
Since you are just saving a HashMap of String objects, you could make a class to cache it for you or make it a static field in the class.
Static fields are fine to use as long as they dont contain a reference to the Activity or a View or Drawable. (That can cause memory leaks)
The simplest way you could do this might just be:
private static HashMap<String,String> myMap = new HashMap<String,String>();
Because this field is static, it will not be recreated when your activity is recreated. Rather, it will still be there for you to use with the same values.
More ways to store data:
(These techniques apply to sharing data over a configuration change also).
http://developer.android.com/guide/faq/framework.html#3
How do I pass data between Activities/Services within a single application?
It depends on the type of data that you want to share:
Primitive Data Types
To share primitive data between Activities/Services in an application,
use Intent.putExtras(). For passing primitive data that needs to
persist use the Preferences storage mechanism.
Non-Persistent Objects
For sharing complex non-persistent user-defined objects for short
duration, the following approaches are recommended:
Singleton class
You can take advantage of the fact that your application components
run in the same process through the use of a singleton. This is a
class that is designed to have only one instance. It has a static
method with a name such as getInstance() that returns the instance;
the first time this method is called, it creates the global instance.
Because all callers get the same instance, they can use this as a
point of interaction. For example activity A may retrieve the instance
and call setValue(3); later activity B may retrieve the instance and
call getValue() to retrieve the last set value. A public static
field/method
An alternate way to make data accessible across Activities/Services is
to use public static fields and/or methods. You can access these
static fields from any other class in your application. To share an
object, the activity which creates your object sets a static field to
point to this object and any other activity that wants to use this
object just accesses this static field.
A HashMap of WeakReferences to Objects
You can also use a HashMap of WeakReferences to Objects with Long
keys. When an activity wants to pass an object to another activity, it
simply puts the object in the map and sends the key (which is a unique
Long based on a counter or time stamp) to the recipient activity via
intent extras. The recipient activity retrieves the object using this
key.
Persistent Objects
Even while an application appears to continue running, the system may
choose to kill its process and restart it later. If you have data that
you need to persist from one activity invocation to the next, you need
to represent that data as state that gets saved by an activity when it
is informed that it might go away.
For sharing complex persistent user-defined objects, the following
approaches are recommended:
Application Preferences
Files
contentProviders
SQLite DB
If the shared data needs to be retained across points where the
application process can be killed, then place that data in persistent
storage like Application Preferences, SQLite DB, Files or
ContentProviders. Please refer to the Data Storage for further details
on how to use these components.
You should probably be overriding the Activity or Fragments onSaveInstanceState(Bundle) function. This will allow you to set any data that you wish to save between instances of the same Activity or Fragment. This is the correct way to save between rotations.
** Updated **
Since you have an ArrayList that contains 1 or more Hashmaps, you might need to save two objects into the bundle. One being the number of HashMaps that are in the array, and then each HashMap. Since the HashMaps are Serializable, you can just use the Bundle.putSerializable to place each of the HashMaps into the bundle. You will need to place the needed information into the bundle in order to re-create the ArrayList in the OnResume().
One method might be this: Have the keys to each HashMap be some string like "Hashmap1", "Hashmap2" and so on for each HashMap. Then if you know the number of HashMaps to retrieve from the bundle and the key format, then you can recreate the ArrayList.

Getting a reference to data collected by a Service from an Activity for visualization purposes

Hello fellow developers,
I am trying to achieve something in Android and I would like some advise on the best practice.
I have created an Activity which can start and stop a Service which collects data.
Instead of simply starting and stopping the Service, the Activity should also display the data collected by the Service.
Here in lies the problem. The data could be quite large so I would like to avoid Serializing and sending it via an Intent. Is it possible to simply get a reference to the data stored in the Service from the Activity?
Simple Example
1) Activity starts
2) Activity starts Service to collect data
3) Activity exists
4) 24 hours pass
5) Activity starts
6) Activity wants to display data collected by Service, but data is quite large.
My question again is simply this. Can the Activity get a reference to the data stored in Service or does the data have to be Serialized and sent from the Service to the Activity using an Intent?
Kind regards,
Cathal
Research android.app.Application class. Essentially you can use this for global state.
http://developer.android.com/reference/android/app/Application.html
Also, any long term data should be stored to a local database. I would try to limit the SELECT to certain number of records to reduce memory footprint.
I've heard that the Application class should not be used in this way necessarily (via Google Team). Instead you could make a separate Singleton class (For example call it "MyData") that holds a public static reference to a let's say ArrayList (For example called "list_data").
So when he activity starts it will call
MyData.list_data = new ArrayList<MyDataObj>();
Then in your Service you can add all of your data objects to this static arraylist like so:
MyData.list_data.add(new MyDataObj());
This allows you to work off of the same ArrayList without passing it around using Intents and etc. Although I would suggest doing some null checking whenevr

Sharing data between services and activities

I have a ListView with a custom ArrayAdapter, that shows orders from an ArrayList. These orders are supposed to be synced with my server. There I have an API, which I am requesting for new orders, and if there are any, I get an XML of the order back. What is the best approach to dynamically update the listView? I do not want to use SQLite to store the orders, because only last ten are supposed to be displayed. With a ContentProvider I am not able to store my custom Order object. And if I wrap the ArrayList into a singleton class and use it in the service as well as in the Activity class for the ArrayAdapter, the ListView is not dynamically updated (probably, because the arrayAdapter makes a copy of the arraylist?). Thank you very much.
Filip
use Intent or Bundle
i'm no sure what you mean regarding the ArrayAdapter not being updated, but i can give you a solution we used in my company.
I have a DataMaanger which is a bridge between the Activities and the Networking or SQLite.
The dataMaanger keeps it's data in memory so it's not in DB or on disk. the disadvantage of it is if your app gets killed for lack of memory and reconstructs itself, the dataManager will be empty, which leaves you with two options, either on every Activitie's death or you main task's activities death you serialize your DataManager's data, or if you are not dependant on any previous data, just make arequest again and update the data manager.
I use broadcasts to notify my activities.
To get an access to the DataManager i don't use a sigletone. i use the Application object, you can extend it and in the Manifest.xml give it's name in the tag, then it will be used instead of the regualr Application object.
You can access it later by using getApplication() method in Activity class.

Another way to pass value from one activity to another activity

Usually we pass value in android from one activity to another activity by Intent function.Is there is any another way is possible to pass the values from one activity to another activity with out Intent function
Yes. Create a class that extends android.app.Application, then in the Manifest put this class as the name of your application
<application android:name=".ClassNameOfTheClassYouCreated"...>
...activities etc here...
</application>
Now, that class that you created is your application. Its lifespan is all the way as long as the application is running, it holds the activities stack and you can add some custom fields to hold your values. To get the Application instance from an Activity, hit this.getApplication().
Edit regarding fields values being reset (in response to the commend by #hackbod): Using static fields on singletons is the other way to hold global values, but I find the proposed one more elegant. As of the case you mention with resetting values, that can also happen in other contexts (like incoming phone call, orientation change), which raises the need to sanitize (or check for existence, call it whatever you like) values before using them. Always!
Information flow can be realized in various way, all you need is a way to save and retrieve your data.
You can save and then get your data which you want it to flow via static class, file storage, database, or even remote storage by using network.
Intent is the better way. Android creates it, so use it. :)
From http://developer.android.com/guide/topics/providers/content-providers.html :
Content providers store and retrieve data and make it accessible to all applications. They're the only way to share data across applications; there's no common storage area that all Android packages can access.
If you want to make your own data public, you have two options: You can create your own content provider (a ContentProvider subclass) or you can add the data to an existing provider — if there's one that controls the same type of data and you have permission to write to it.

Categories

Resources