I have several Activities in a program. Lets say, activities A, B and C.
Activity A is the main activity in this context. It contains object X, that must be accessible for all other activities (Activities: B and C).
Activity A will start activity B and then B will start ะก. After that both activities A and B are in the background and can be killed by the OS. How should I pass object X to activities B and C in order to be sure that object X will not be killed when A&B are killed?
Why don't you can create your X Object with SingleTon ? You can keep it alive as long as you want and you can get the same Instance from where ever you want.
public class TestObject {
private static TestObject testObjectInstance;
/* put you data here */
private TestObject() {
}
public TestObject getTestObjectInstance() {
if (testObjectInstance != null) {
return testObjectInstance;
} else {
testObjectInstance = new TestObject();
return testObjectInstance;
}
}
public TestObject createNewTestObjectInstance() {
testObjectInstance = new TestObject();
return testObjectInstance;
}
}
The best way will be to save X value in Shared Preferences.The Value of X will be retained even your A and B activities are killed.
Check this Link for How to use Shared Preferences:
How to use SharedPreferences in Android to store, fetch and edit values
There are three possible ways:
Two of them were mentioned here.
Via SharedPreferences. But remember that the SharedPreferences retain the value when the application is closed. This is the best solution if you want the value to be "permanent" on your application.
Creating a singleton object. This is the best solution if you want to manipulate the object in all activities but don't want to save it for another runs.
Sending the data via extras. This is the best solution if you only want the VALUE of the object and don't want to manipulate it.
try the putExtra() function in Intent
You can only use it for primitives.
If your X is contains only primitives, you may write a function in X,public Intent fillIntentWithX(Intent intent) which take the intent object as argument, and fill the intent object with the primitives in X, and return the intent object.
similarly, write another function in X, public X getXFromIntent(Intent intent) which takes an intent as an argument, extracts the primitives residing in it to form a new object X, and return it.
use fillIntentWithX() to fill the intent, which launches B, with the
object X's properties.
use getXFromIntent() to extract X out in
activity B, and so on.
Related
I have a service called EventReceivingSevice which will get new data in onDataRefresh(JSONObject data) function.
private void onNewData(JSONData data) {
boolean isActive=isActivityActive(); //Check if activity is active
if(isACtive)
passData(data);
else
storeData(data);
}
An activity called HomeActivity will display the data. When EventReceivingService will get new data, it has to be checked if HomeActivity is active, it has to pass the data to HomeActivity, and if not it will store the data somewhere so that HomeActivity will later use that.
The data is in JSON format.
How can achieve this?
You can't reliably determine if an Activity is active. What you should do is to store the data somewhere (file, SQLite database, etc.), and then send a broadcast Intent that means "new data is available". Your Activity can register a listener that will get triggered by that broadcast Intent if the Activity is alive when the broadcast Intent is sent. It can then pick up the data from wherever you put it and do whatever you want with it.
There is a simple method but it doesn't require JSON data. you can just add data as public static data.
public static int GRID_COUNT = 2;
If you are using that data for reading purposes, you can do it like this.
public static final int GRID_COUNT = 2;
I have a problem with with sharing data between two different activities. I have data like :
int number
String name
int number_2
int time
int total
I'm trying to make something like order list with this set of data . So it will take one set of data , then back to previous activity , move forward and again add data to it .
I have an idea of making it in array of object - but data inside was cleared after changing activity.
How can I make it ?
I don't know if and how to add Array of object to SharedPreferences , and get value of one element from there.
You should have a look at the documentation of the Intent(s) if you want to do that on the fly associating a key to the value(s) that you want to pass to your second activity.
Anyway, you can think any(sharedpref, database,...) way to pass your parameters but for those kind of things it's a convention and a good practice to follow that.
Don't used share preferences for this...Use the singleton pattern, extend Application, or just make a class with static variables and update them...
You can use .putExtra but since you are communicating with more than one activity the above suggestions are probably the best.
public class ShareData {
private String s;
private int s;
private static ShareData shareData = new ShareData();
private ShareData(){}
public static ShareData getInstance(){ return shareData}
//create getters and setters;
}
Why not to use Intents
Intent intent = new Intent(FirstActivity.this, (destination activity)SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);
in the second activity
Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");
EDIT if you want to read more about adding array to shared preferences check this
Is it possible to add an array or object to SharedPreferences on Android
also this
http://www.sherif.mobi/2012/05/string-arrays-and-object-arrays-in.html
I want to add a HashMap to a singelton (which will be the application instance object) to pass data between activites. I cant use a Bundle as the objects are too big to be passed through an intent.
I'm currently using this implementation:
public class MyApp extends Application {
private static MyApp singelton;
private static Map<String, Object> tempDataStorage;
#Override
public void onCreate() {
super.onCreate();
singelton = this;
tempDataStorage = new HashMap<String, Object>();
}
// puts the object in the Map and returns the key
public static String putDataInStorage(Object data) {
String key = UUID.randomUUID().toString() // generate a key
tempDataStorage.put(key, data);
}
// gets the object from the Map and deletes it to save memory
public static Object getDataFromStorage(String key) {
Object o = tempDataStorage.get(key);
tempDataStorage.remove(key);
}
}
putDataInStorage() is called from activity A to pass the data to activity B which then calls getDataFromStorage() with the key passed through the intent. If activity B gets destroyed by android, it also calles putDataInStorage() in its onSaveInstanceState() method to reclaim the data later.
Im still having a problem with android destroying my application after some time if the app is not used. If the user then comes back, it seems to recreate Activity B with the Bundle from saveInstanceState, while the new HashMap is empty.
I first thought about writing the Data from the Map into an SQL-Database when the app is destroyed and recreate the objects on recreation. But this would lead into an endlessly growing Map (and therfore endlessly growing memory usage) as the objects would never disappear. Not a good solution though.
As the data is fetched from a webserver, my second idea was to also save a reference to the data in the saveInstanceState() of Activity B (eg. the parameters of the GET-request). If activity B is then confronted with a NullPointerException, it can refetch the data.
Is that a good solution? If not, whats a better one?
Thanks for your help!
You should not count on saving dynamic data. Application can be killed at any time when other apps need memory. Use SharedPreferences to save your data permanently.
I'd like to pass a custom Object from one activity to another, the Object consists of a String and a List of another custom Object which consists of an array of strings and an array of ints. I've read https://stackoverflow.com/a/2141166/830104, but then I've found this answer https://stackoverflow.com/a/7842273/830104. Which is better to use Bundle or Parcelable? What is the difference? When should I use this each? Thanks for your replies, Dan
Parcelable and Bundle are not exclusive concepts; you can even deploy both on your app at a time.
[1] Term Parcelable comes with Serialization concept in Java (and other high-level language such as C#, Python,...). It ensures that an object - which remains in RAM store - of such Parcelable class can be saved in file stream such as text or memory (offline status) then can be reconstructed to be used in program at runtime (online status).
In an Android application, within 2 independent activities (exclusively running - one starts then other will have to stop):
There will be NO pointer from current activity to refer to previous one and its members - because previous activity is stopped and cleared out form memory; so that to maintain object's value passed to next activity (called from Intent) the object need to be parcelable (serializable).
[2] While Bundle is normally the Android concept, denotes that a variable or group of variables. If look into lower level, it can be considered as HashMap with key-value pairs.
Conclusion:
Bundle is to store many objects with related keys, it can save any object in native types, but it doesn't know how to save a complex object (which contains an ArrayList for example)
Parcelable class is to ensure a complex instance of it can be serialized and de-serialized during runtime. This object can contains complex types such as ArrayList, HashMap, array, or struct,...
[UPDATED] - Example:
//Class without implementing Parcelable will cause error
//if passing though activities via Intent
public class NoneParcelable
{
private ArrayList<String> nameList = new ArrayList<String>();
public NoneParcelable()
{
nameList.add("abc");
nameList.add("xyz");
}
}
//Parcelable Class's objects can be exchanged
public class GoodParcelable implements Parcelable
{
private ArrayList<String> nameList = new ArrayList<String>();
public GoodParcelable()
{
nameList.add("Can");
nameList.add("be parsed");
}
#Override
public int describeContents()
{
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags)
{
// Serialize ArrayList name here
}
}
In source activity:
NoneParcelable nonePcl = new NoneParcelable();
GoodParcelable goodPcl = new GoodParcelable();
int count = 100;
Intent i = new Intent(...);
i.putExtra("NONE_P",nonePcl);
i.putExtra("GOOD_P",goodPcl);
i.putExtra("COUNT", count);
In destination activity:
Intent i = getIntent();
//this is BAD:
NoneParcelable nP = (NoneParcelable)i.getExtra("NONE_P"); //BAD code
//these are OK:
int count = (int)i.getExtra("COUNT");//OK
GoodParcelable myParcelableObject=(GoodParcelable)i.getParcelableExtra("GOOD_P");// OK
I have two activities, Activity A and Activity B. I pass objects from Activity A to Activity B using intents. When i make changes to the Object in Activity B the data changes does not get reflected in Activity A. Have i missed out on something?
You are missing the fact that when you pass Object O from Activity A to Activity B via intents, activity B receives a COPY of object O. The way things work is that The object O gets serialized (converted to a sequence of bytes) and that sequence of bytes is then passed to Activity B. Then activity B recreates a copy of object O at the moment it was serialized. Any changes to the original object after it was serialized are not reflected in it's copy.
If both activities are part of the same application then just use a static field (or singleton) to communicate between them.
If you are passing a String, then it will not change since they are immutable.
Edit: See below for an alternative to Intent extras.
If you wish to use the architecture of passing immutable objects in messages you can create an immutable serializable data class. Pass an immutable instance of the data class in the intent using startActivityForResult. When the second activity is completed, send a different instance of the same immutable data class back to the first activity where it is trapped in onActivityResult. So in code, given an immutable class PasswordState.java with public final fields.
public final class PasswordState implements Serializable {
Create an instance of this immutable class and send it to the second activity as in:
private void launchManagePassword() {
Intent i= new Intent(this, ManagePassword.class); // no param constructor
PasswordState outState= new PasswordState(lengthKey,
timeExpire,
isValidKey,
timeoutType,
password,
model.getIsHashPassword(),
model.getMinimumPasswordLength()); // NOT minimumHashedPasswordLength
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outState);
i.putExtras(b);
startActivityForResult(i,REQUEST_MANAGE_PASSWORD); // used for callback
}
The second activity returns a new object when it is done.
PasswordState outPasswordState= new PasswordState(lengthKey,
timeExpire,
isValidKey,
timeoutType,
password,
isHashPassword,
minimumPasswordLength);
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outPasswordState);
getIntent().putExtras(b);
setResult(RESULT_OK,getIntent()); // call home with data on success only
finish(); // go back <=== EXITS Here
Where it is trapped in Activity one.
// ON_ACTIVITY_RESULT used for callback from ManageKeys.java
protected void onActivityResult(int request, int result, Intent data)
{
switch (request){
case REQUEST_MANAGE_PASSWORD:
if (result == RESULT_OK) { // Success. New password.
try {
PasswordState inMessage= (PasswordState)data.getSerializableExtra("jalcomputing.confusetext.PasswordState");
password= inMessage.password;
timeExpire= inMessage.timeExpire;
isValidKey= true;
writeToPrefs(); // support first launch and incoming tagged sms, save pw
}
catch(Exception e){ // data == null, extras == null
password= "";
isValidKey= false;
timeExpire= PasswordState.LONG_YEAR_MILLIS;
Log.d(Utilities.TAG,"FailedToGetResult",e); // will be stripped at runtime
}
...
break;
}
}
When you are done prototyping and the data objects are stable, you can refactor the code to use parcels instead of serializing objects. Since a copy is being sent between activities using serialization, it could be argued that the use of an immutable object is overkill. Using a mutable object and serializing a mutable object to and from the second activity would simplify the implementation.
Hope that helps.
JAL