Another way that you can exchange data between activities - java

What is different between static field and other ways in store data when the application is run?
I'm using static fields for pass data between activities and worked perfectly:
I defined this class :
public class Info
{
public static int ID = 0;
public static String NAME = "TEST";
public static TestClass testclass = null;
}
and I can store my data anywhere:
Info.ID = 5;
Info.NAME = "USER!";
Info.testclass = new TestClass();
and I can get my data anywhere:
Info.ID
Info.NAME
Info.testclass

It is usual to pass data between activities using extras within the intent. Such data persists for the lifetime of the receiving activity (when finished with, the garbage collector can free up the memory).
Or you can store values using SharedPreferences. These will persist between sessions and are stored as key/value pairs in a file (so don't impact memory use as such).
Or you can hold values in static fields (as you are doing here) which persist for the lifetime of your application session. However there is a significant risk with this in that the garbage collector cannot free up memory that is referenced by such fields unless you set them to null when you no longer need the reference. You should never store a reference to an activity/context/view in a static field since you'll leak the entire activity which can amout to a significant amount of memory usage.
http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html
You can pass a class instance within an intent if it is Serializable, e.g.:
Intent intent = new Intent(this, whatever.class);
Bundle b = new Bundle();
b.putSerializable("data", my_object);
intent.putExtras(b);
startActivity(intent);
And in the receiving activity, cast it back to whatever class your object is:
Bundle b = getIntent().getExtras();
my_object = (whatever class is it) b.getSerializable("data");
Many java classes implement Serializable and it is very simple to make your own classes serializable too.

If you're changing activities I'm assuming you're using intents. What you can do is send data with the intent with myIntent.putExtra("some string",someString);.
Then you can receive the info in your new activity using
Intent intent = getIntent();
String someString = intent.getExtra("some string");

You can use intents for passing data between activities.
Your first Activity.java
public void onClick(View v)
{
Intent timer = new Intent (FirstActivity.this,SecondActivity.class);
timer.putExtra("beefType", 5000);
startActivity(timer);
}
Then in your SecondActivity.java file do:
nt beefType = getIntent().getIntExtra("beefType", -1);

You want to share data between activities,you can use intent or shared prefernce.
The difference in using these tow and static data is that,intent and shared prefrence ,at some static data can be empty or null.but sending data using above two methods gurantees that you will get data in next activity ,unless you forcefully remove preference
you can refer this link for more info Static class in Java (Android) - use or not use

There is something called an Application Class in android. Its like a global singleton.
In other words, that Application Class will be common for that entire application.
Application class will be that first class to load.
So it will be easier to store some randomly used values in the application class.
public class Info extends Application
{
public static int ID = 0;
public static String NAME = "TEST";
}
Then call it in any activity by:
Info info= ((YourApplication)this.getApplication());
And in your manifest:
<application
android:name="<your package name>.GlobalApplication">
........
........
</application>

Well, that way doesn't always work in Android. Your static values are hold only while your app is running. Imagine you are sharing some content with action SEND, so you are starting another app which actually share your content (Facebook, email, etc.). Android may decide to stop completely your app if there are no resources enough to launch other app. In that point, the process of your app is completely gone and, with it, your static values. When going back to your app from the app that shared the content, you've lost your values.
I'd better use Intent extras, combined with Parcelable objects if you need to serialize more complex data.
You can easily try it if you enable in a device the option Don't keep activities under developer options, which destroys every activity as soon as the user leaves it.

Related

Pass object to another activity (without Parcelable?)

I need to pass object user to another activity. I know I should use Parcelable, but I can't edit User class, because it is used from maven repository.
Is it here any other way how can I pass user object? Or how to locally edit class from maven repository?
You can use the Application class for this purposes.
what you need is:
create a class which derives from Application.
declare the class in the AndroidManifest.xml (see here)
create a object variable of type User in it (also getter and setter).
assign the user object in first activit through:
MyApplication app = (MyApplication) getApplication();
app.setUser(user);
retrieve the object in other activity through:
MyApplication app = (MyApplication) getApplication();
User user = app.getUser();
BUT: take care, after you restart you app (go in background and open it again), a new Application object will be created, where the User is null, take care of that then.
This problem can be read here.
Hope this helps.
You can serialize the object into some kind of string representation. The easiest way to do this is to convert the object into a JSON string, pass the string to the other activity via intent and convert the string back into the original object.
What I am doing is just converting the object into Json and then sending as a String using Intent. Then you can't catch it and parse Json.
P.S. Using google's Gson class making this very easy. https://code.google.com/p/google-gson/

How to I can call a method from another activity with passing data?

I have 2 activities.
I start one, and at a point I start another one:
Intent enabler = new Intent(this, cprompt.class);
startActivity(enabler);
I want to call a method from the old one, but I want to pass some data too.
This is how I tried:
Activity1.sendcommand(DATA);
And I got this:
Cannot make a static reference to the non-static method sendcommand(String) from the type Activity1
And I don't want change the method to static.
The only way if I make a Listener? If I have to, you can describe for me to how?
The java is new for me... :/ But if this problem is solved I think I am done with my program :)
Only one Activity is active at a time. Are you trying to trigger the method just because you want to pass some data?.You can do it via an Intent
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("YOUR_DATA_KEY", "Data Value");
startActivity(intent);
and in the SecondActivity , you can retrieve the data and process it
String data = getIntent().getStringExtra("YOUR_DATA_KEY");
It's not just Strings that you can send this way.You can even transmit Serializable and Parcelable Extras. For more information refer - Intents on Android Developer Website
You can declare an interface and make Activity1 implements that interface..
Then when you need to call Activity1's method call the inetrface's method...
Your interface:
public interface OnSendCommand{
public void onSendCommand(values);
}
Activity1:
public Activity1 implements OnSendCommand {
public void onSendCommand(values){}
}
Are you returning to the first activity from the second when executing this method? If so you could use startActivityForResult() following this tutorial. If not, then something is wrong with the structure of your application if this method can not be static, and this method should be in a separate class not inheriting from Activity.

Android Application class - lifecycle of field members

I have Android application and own Application derived class holding some internal data.
Among other there are some string fields. The problem is that if I put the application in foreground, work on other application, switch back to my app again, the app may be restarted because it got killed by system. Unfortunatelly the Application object seems not to be created again because the onCreate method of application object doesn't get called and all fields are set to null. My Activity gets recreated but all Application's object fields are null. When is the Application.onCreate method called? How to handle it?
there is no onCreate that you can register to.in later API's there's a way to register to the Activity lifecycle functions. and then you can do what ever you want.
basically, what you should do is use SharedPrefrences for storing information.
what I would do is:
class MyApp extends Application {
private static String someResource = null;
public static String getSomeResource(Context context) {
if(someResource == null) {
SharedPrefrences prefs = (SharedPrefrences)
context.getSystemService(Context.SHARED_PREFRENCES);
someResource = prefs.getString(SOME_RESOURCE, null);
}
return someResource;
}
Application onCreate() will called only for one time during its life-cycle, i.e.. only when application is started.
As suggested by thepoosh below answer is valid ,if your application is killed,still the data is saved in shared preference.

Losing 'MediaPlayer' (& other Variables) when Device is Rotated

I'm creating a music player for Android and it's mostly working. The problem is that when I turn the device horizontally I lose all the variables from the Activity (which makes sense because it is destroyed and re-created).
I've tried using bundles to store the state of the player with onSaveInstanceState & onRestoreInstanceState but I still can't access the media player. Is there a way to pass objects like the MediaPlayer in bundles? Should I be using a database instead?
Thanks
You should use a Service to Provides "background" audio playback capabilities, allowing the
user to switch between activities or Rotate device without stopping playback.
Check out android_packages_apps_Music which is opensource by CM on github , It use MediaPlaybackService extends Service to do this , checkout MediaPlaybackService.java
For objects you couldn't pass via a bundle, I would suggest you to use the simple SharedPreference to store objects.
Here you have a simple implementation:
public class Data {
private SharedPreferences preferences;
private int test;
public Data (Context context)
{
preferences = context.getSharedPreferences("Data", 0);
test = preferences.getInt("test", 0);
}
public int getTest()
{
return test;
}
public void setTest(int input)
{
this.test = input;
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("Test", input);
editor.commit();
}
}
You have just to initialize the variable in the onCreate():
Data mydata = new Data(this);
And you can use set/get with mydata to store/retrieve your persistent data.
Edit: It is maybe not suitable for MediaPlayer objects, but for other classical types (int, string, boolean...).
Both of the methods below would allow you to keep your mediaplayer object through the rotation, but neither use bundles.
You could persist your media player by using onRetainNonConfigurationInstance() to save the variable and getLastNonConfigurationInstance() to retrieve it after the rotation, but this method isn't necessarily the best as it is not always called
-See this SO post for more info https://stackoverflow.com/a/3916068/655822
Or you could persist your media player by extending your application class and storing it in there
below info copied from the linked SO answer for the purpose of making this answer quicker to read
You can pass data around in a Global Singleton if it is going to be used a lot.
public class YourApplication extends Application
{
public SomeDataClass data = new SomeDataClass();
}
Then call it in any activity by:
YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here.
-See this SO post for more info on that https://stackoverflow.com/a/4208947/655822
Another way would be to :
In your AndroidManifest.xml, find your entry for your activity and add the following attribute and value:
android:configChanges="orientation|screenSize"
This will stop your activity from being destroyed and recreated on orientation.

Is this a memory leak?

I have a ListActivity containing an object I've defined called a MessageItem. I want to pass the data in this MessageItem off to a Service to do some stuff, but I don't want the Activity to be data bound to the Service such that Android can't reclaim the Activity if it needs to (ergo memory leak).
What I'm doing is passing the MessageItem object to a method in a singleton class along with the application Context. The singleton method uses the application Context to start my Service. I pass to this Service an Intent. In this Intent, I put items from the MessageItem object like so:
intent.putExtra("subject", msg.getSubject());
intent.putExtra("summary", msg.getSummary());
intent.putExtra("created_on", msg.getCreatedDate());
intent.putExtra("read", msg.getIsRead());
Will this data bind my Activity to the Service the Intent gets passed into and cause a memory leak?
Would this be a better implementation?:
intent.putExtra("subject", new String(msg.getSubject()));
intent.putExtra("summary", new String(msg.getSummary()));
intent.putExtra("created_on", new Integer(msg.getCreatedDate()));
intent.putExtra("read", new Boolean(msg.getIsRead()));
You don't need to new String or Integer. When the data is transfered by intent,
It will be parceled and unparceled.
Will this data bind my Activity to the Service
No, the code above will the references in the activity to the intent. The string and boolean values have no pointer back to the instance.
Would this be a better implementation?
No! That would be much worse. A lot of data would be copied and a lot of objects would be created for naught.

Categories

Resources