I've got an object that I use to interact with various things. The object itself is initialized in my first activity and used in all subsequent activities. What's the best way to make it "public" to all activities?
Create a class that extends Application and hold the instance there.
class MyApp extends Application{
private Object obj;
public Object getObject(){
return obj;
}
}
Then in your Activity
MyApp ma = (MyApp)getApplicationContext();
Object o = ma.getObject();
You can read more about the Application class on the android developer website: http://developer.android.com/reference/android/app/Application.html
public class MyStorage {
private static MyStorage ourInstance = new MyStorage();
public static MyStorage getInstance() {
return ourInstance;
}
private MyStorage() {
}
public HashMap<String,Object> storage=new HashMap<String, Object>();
}
//put data
MyStorage.getInstance().storage.put("mykey", obj);
//get data
Object obj=MyStorage.getInstance().storage.get("mykey");
Related
In my application i have to share various java-beans class among the activities.
In order to do that, i extended the Application class, in which i create an HashMap filled with all the java-beans. Each java-beans has its own Key.
Example code:
public class MyApplication extends Application {
public static final String CLASSROOM_KEY = "Classroom";
private HashMap<String, Object> myObjects;
#Override
public void onCreate() {
myObjects = new HashMap<String, Object>();
myObjects.put(CLASSROOM_KEY, new Classroom());
}
public HashMap<String, Object> getMyObjects() {
return myObjects;
}
}
This is usable in all the activities, and this is ok. BUT, i have two problems:
1) I need to get myObjets also in non-activity classes, like utils classes, but in these classes i can't do "getApplicationContext()" because they don't extend Activity.
For example, from my main activity i start a service (but it is in a normal class), and the service calls a query that in turn is in another normal class.
The query needs an object that is in myObjects!
I can't make myObjects public static i think.
2) In MyApplication i have to create all my java-beans in advance.
What if in the future i wanted to create a new classroom object in addition to the already present one?
I should create a new key for it, but it is impossible!
Thanks for your help.
UDPATE
I change the question:
In this class:
public class ClassroomUtils {
private static String result = null;
private static String studentObjectID = null;
public static void queryClassroom(String UUID, final Classroom classroom) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Classroom");
query.whereEqualTo("BeaconUUID", UUID);
query.getFirstInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
try {
result = object.getString("Label");
} catch(Exception e1){
System.out.println("Vuota");
}
if(result != null) {
Log.i("Classroom", "Retrieved " + result );
classroom.setClassroom(result);
sendNotification(result);
addStudentClassroomRelation(object);
}
} else {
Log.e("Classroom", "Error: " + e.getMessage());
}
}
});
}
i want to avoid to pass the classroom to this method (called from another normal class). How can i access to global objects from this class?
I can't make myObjects public static i think.
Why not? myObjects is effectively global in scope already. There is nothing to be gained, from a memory management standpoint, by having myObjects be a private data member of Application. If you want Classroom to be a Java singleton, do so. You just have to watch your memory management, as you do with your current implementation.
In MyApplication i have to create all my java-beans in advance
No, you do not.
What if in the future i wanted to create a new classroom object in addition to the already present one?
Then create another one. Perhaps the right singleton is a School, which holds onto a collection of Classroom objects. Again, your primary near-term issue is one of memory management, so you do not run out of memory because you are trying to keep these objects around all of the time.
1) I need to get myObjets also in non-activity classes, like utils classes, but in these classes i can't do "getApplicationContext()" because they don't extend Activity.
The best way, I think, is to create the MyApplication class as a singleton. There you can retrieve the data from anywhere by calling getInstance and the corresponding getter/setter for your attributes.
Short example:
public class MyApplication extends Application {
private static MyApplication mInstance;
public MyApplication getInstance(){
// this means you have only one existing instance of this class.
if(mInstance == null){
// set the context to this MyApplication instance
mInstance = this;
}
// return the instance of this class
return mInstance;
}
// here your stuff for MyApplication
public HashMap<String, Object> getMyObjects() {
return myObjects;
}
}
Then you can call it from another class like this:
public class CFoo{
public CFoo(){
//retrieve myObjects from MyApplication
MyApplication.getInstance().getMyObjects();
}
}
I hope that we can pass data between android application components
by following ways.
1.we can pass data using intent object,
2.we can implement serializable , parcelable interface and pass objects by using intent,
3.we can create a new class by extending Application class, to access global members from anywhere
the android application,
4.sharedpreference ,
5.sqlite.
Are there any other mechanism to send data between android application components?
Another option is create ApplicationPool.
Follow the below steps:-
Initiate the ApplicationPool :-
ApplicationPool pool = ApplicationPool.getInstance();
modify the data on details page and add to pool
pool.put("key", object);
get the modified data on list page from pool
Object object = (Object) pool.get("key");
important notes:- notify the listview or gridview after getting the data
ApplicationPool class file
public class ApplicationPool {
private static ApplicationPool instance;
private HashMap<String, Object> pool;
private ApplicationPool() {
pool = new HashMap<String, Object>();
}
public static ApplicationPool getInstance() {
if (instance == null) {
instance = new ApplicationPool();
}
return instance;
}
public void clearCollectionPool() {
pool.clear();
}
public void put(String key, Object value) {
pool.put(key, value);
}
public Object get(String key) {
return pool.get(key);
}
public void removeObject(String key) {
if ((pool.get(key)) != null)
pool.remove(key);
}
}
Another way is to use static elements, wether it be:
Static fields (with public access for example)
Static properties (meaning private fields with getter and/or setter)
Singletons
Possibly nested classes
While the use of static variables in OOP is debatable, they introduce global state and therefore are a way to accomplish sharing of data inbetween activities too.
1) HashMap of WeakReferences, for example:
public class DataHolder {
Map<String, WeakReference<Object>> data = new HashMap<String, WeakReference<Object>>();
void save(String id, Object object) {
data.put(id, new WeakReference<Object>(object));
}
Object retrieve(String id) {
WeakReference<Object> objectWeakReference = data.get(id);
return objectWeakReference.get();
}
}
Before launching the activity:
DataHolder.getInstance().save(someId, someObject);
From the launched activity:
DataHolder.getInstance().retrieve(someId);
2) Or strange method: store data on server O_o
I have a problem passing an arraylist of complex object between 2 activity, the object (ObjA) is something like this:
ObjA:
-String
-Array of ObjB
where ObjB is:
ObjB:
-String
-Array of ObjC
where ObjC is:
ObjC:
-String
-String
the 3 object are serializable:
public class Obj implements Serializable{
private static final long serialVersionUID = 1L;
}
I try to pass the object as a normal extras but the app crash without any log, how can I pass this array?
The 3 obj are serialazible, they have this form:
public class Materia implements Serializable{
private static final long serialVersionUID = 1L;
String titolo;
String icona;
ArrayList<Sezione> sezioni;
public Materia (){}
public String getTitolo() {
return titolo;
}
public void setTitolo(String titolo) {
this.titolo = titolo;
}
public String getIcona() {
return icona;
}
public void setIcona(String icona) {
this.icona = icona;
}
public ArrayList<Sezione> getSezioni() {
return sezioni;
}
public void setSezioni(ArrayList<Sezione> sezioni) {
this.sezioni = sezioni;
}
}
1. Using Application class
You can do this using your Application object. This way, you can define a getter and setter method in your application class and use them in activities:
public class MyApp extends Application {
private Object obj;
public void setObject(Object obj) {
this.obj = obj;
}
public Object getObject() {
return obj;
}
}
Usage in activities:
MyApp app = (MyApp) getApplication();
app.setObject(/* your complex object */);
And in your second Activity:
MyApp app = (MyApp) getApplication();
Object complexObj = app.getObject();
This is a bad approach. User when switches to another app, Android may kill your app (i.e. the process your app in running in), specially when device is running on low memory. After your app being killed, if user comes back to your app, the Application class is re-instantiated and thereby the obj reference inside being null.
2. Make your complex object implements Serializable or Parcelable
Refer to: Android: Difference between Parcelable and Serializable?
If all the three objects are serializable then,
In Calling activity:
ObjA a = new ObjA();
Intent i = new Intent(this, SecondActivity.class);
i.putExtra("t", a);
startActivity(i);
In called activity:
ObjA a=(ObjA) getIntent().getSerializableExtra("t");
I have followed this link and successfully made singleton class in Android.
http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/
Problem is that i want a single object. like i have Activity A and Activity B. In Activity A I access the object from Singleton class. I use the object and made some changes to it.
When I move to Activity B and access the object from Singleton Class it gave me the initialized object and does not keep the changes which i have made in Activity A.
Is there any other way to save the changing?
Please help me Experts.
This is MainActivity
public class MainActivity extends Activity {
protected MyApplication app;
private OnClickListener btn2=new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent=new Intent(MainActivity.this,NextActivity.class);
startActivity(intent);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get the application instance
app = (MyApplication)getApplication();
// Call a custom application method
app.customAppMethod();
// Call a custom method in MySingleton
Singleton.getInstance().customSingletonMethod();
Singleton.getInstance();
// Read the value of a variable in MySingleton
String singletonVar = Singleton.customVar;
Log.d("Test",singletonVar);
singletonVar="World";
Log.d("Test",singletonVar);
Button btn=(Button)findViewById(R.id.button1);
btn.setOnClickListener(btn2);
}
}
This is NextActivity
public class NextActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
String singletonVar = Singleton.customVar;
Log.d("Test",singletonVar);
}
}
Singleton Class
public class Singleton
{
private static Singleton instance;
public static String customVar="Hello";
public static void initInstance()
{
if (instance == null)
{
// Create the instance
instance = new Singleton();
}
}
public static Singleton getInstance()
{
// Return the instance
return instance;
}
private Singleton()
{
// Constructor hidden because this is a singleton
}
public void customSingletonMethod()
{
// Custom method
}
}
and MyApplication
public class MyApplication extends Application
{
#Override
public void onCreate()
{
super.onCreate();
// Initialize the singletons so their instances
// are bound to the application process.
initSingletons();
}
protected void initSingletons()
{
// Initialize the instance of MySingleton
Singleton.initInstance();
}
public void customAppMethod()
{
// Custom application method
}
}
When i run this code, i get Hello which i have initialized in Singleton then World which i gave it in MainActivity and again shows Hello in NextActivity in logcat.
I want it to show world again in NextActivity.
Please help me to correct this.
Tip: To create singleton class In Android Studio, right click in your project and open menu:
New -> Java Class -> Choose Singleton from dropdown menu
EDIT :
The implementation of a Singleton in Android is not "safe" (see here) and you should use a library dedicated to this kind of pattern like Dagger or other DI library to manage the lifecycle and the injection.
Could you post an example from your code ?
Take a look at this gist : https://gist.github.com/Akayh/5566992
it works but it was done very quickly :
MyActivity : set the singleton for the first time + initialize mString attribute ("Hello") in private constructor and show the value ("Hello")
Set new value to mString : "Singleton"
Launch activityB and show the mString value. "Singleton" appears...
It is simple, as a java, Android also supporting singleton. -
Singleton is a part of Gang of Four design pattern and it is categorized under creational design patterns.
-> Static member : This contains the instance of the singleton class.
-> Private constructor : This will prevent anybody else to instantiate the Singleton class.
-> Static public method : This provides the global point of access to the Singleton object and returns the instance to the client calling class.
create private instance
create private constructor
use getInstance() of Singleton class
public class Logger{
private static Logger objLogger;
private Logger(){
//ToDo here
}
public static Logger getInstance()
{
if (objLogger == null)
{
objLogger = new Logger();
}
return objLogger;
}
}
while use singleton -
Logger.getInstance();
answer suggested by rakesh is great but still with some discription
Singleton in Android is the same as Singleton in Java:
The Singleton design pattern addresses all of these concerns. With the Singleton design pattern you can:
1) Ensure that only one instance of a class is created
2) Provide a global point of access to the object
3) Allow multiple instances in the future without affecting a
singleton class's clients
A basic Singleton class example:
public class MySingleton
{
private static MySingleton _instance;
private MySingleton()
{
}
public static MySingleton getInstance()
{
if (_instance == null)
{
_instance = new MySingleton();
}
return _instance;
}
}
As #Lazy stated in this answer, you can create a singleton from a template in Android Studio. It is worth noting that there is no need to check if the instance is null because the static ourInstance variable is initialized first. As a result, the singleton class implementation created by Android Studio is as simple as following code:
public class MySingleton {
private static MySingleton ourInstance = new MySingleton();
public static MySingleton getInstance() {
return ourInstance;
}
private MySingleton() {
}
}
You are copying singleton's customVar into a singletonVar variable and changing that variable does not affect the original value in singleton.
// This does not update singleton variable
// It just assigns value of your local variable
Log.d("Test",singletonVar);
singletonVar="World";
Log.d("Test",singletonVar);
// This actually assigns value of variable in singleton
Singleton.customVar = singletonVar;
I put my version of Singleton below:
public class SingletonDemo {
private static SingletonDemo instance = null;
private static Context context;
/**
* To initialize the class. It must be called before call the method getInstance()
* #param ctx The Context used
*/
public static void initialize(Context ctx) {
context = ctx;
}
/**
* Check if the class has been initialized
* #return true if the class has been initialized
* false Otherwise
*/
public static boolean hasBeenInitialized() {
return context != null;
}
/**
* The private constructor. Here you can use the context to initialize your variables.
*/
private SingletonDemo() {
// Use context to initialize the variables.
}
/**
* The main method used to get the instance
*/
public static synchronized SingletonDemo getInstance() {
if (context == null) {
throw new IllegalArgumentException("Impossible to get the instance. This class must be initialized before");
}
if (instance == null) {
instance = new SingletonDemo();
}
return instance;
}
#Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Clone is not allowed.");
}
}
Note that the method initialize could be called in the main class(Splash) and the method getInstance could be called from other classes. This will fix the problem when the caller class requires the singleton but it does not have the context.
Finally the method hasBeenInitialized is uses to check if the class has been initialized. This will avoid that different instances have different contexts.
The most clean and modern way to use singletons in Android is just to use the Dependency Injection framework called Dagger 2. Here you have an explanation of possible scopes you can use. Singleton is one of these scopes. Dependency Injection is not that easy but you shall invest a bit of your time to understand it. It also makes testing easier.
I'm trying to create an ArrayList of Data containing Objects (Like a list of Addresses and properties (pretty complex)) and am wondering: How can I make an Object accessible (and editable) by all Activities and not just the one it was instanciated in?
Basically this:
Create Array in Activity 1
Access same Array in Activity 2 and 3
???
Profit.
The easiest way to do this is by creating an Singleton. It's a kind of object that only can be created once, and if you try to access it again it will return the existing instance of the object.
Inside this you can hold your array.
public class Singleton {
private static final Singleton instance = new Singleton();
// Private constructor prevents instantiation from other classes
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
Read more about singleton:
http://en.wikipedia.org/wiki/Singleton_pattern
You can extend the application class. And add your arrays there.
You can access the instance of the class by using this command
MyApplication appContext = (MyApplication)getApplicationContext();
Well you can create a Constant class and declare you ArrayList as a static variable.
1.)
Class ConstantCodes{
public static ArrayList<MyClass> list = new ArrayList<MyClass>;
}
This will be accessible from everywhere you want by just ConstantCodes.list
2.) You can extend your class by Application class like this
class Globalclass extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class TempActivity extends Activity {
#Override
public void onCreate(Bundle b){
...
Globalclass appState = ((Globalclass)getApplicationContext());
String state = appState.getState();
...
}
}
you should make it static and access it from any other activity.....
how about use a static keyword ?
public static SomeClass someObject
in your activity class that initiate your object
1- In your Activity1, déclare your array in public static
public static ArrayList<HashMap<String, String>> myArray = new ArrayList<HashMap<String, String>>();
2- In your Activity2, Activity3, etc. access to your ArrayList
Activity1.myArray
You can create a java file x beside other java files.
x file contains static method which used to access the class method without instantiate it.
Now make a method called createVariable() and declare variable which you want to make it Global.
Now make a method called getVariable() which returns the Global variable.
At which point you want to create global variable, call className.createVariable().
And to get access to that variable call className.getVariable().
Here is my example for Database class.
public class GlobalDatabaseHelper{
static DatabaseHelper mydb;
public static DatabaseHelper createDatabase(Context context)
{
mydb = new DatabaseHelper(context);
return mydb;
}
public static DatabaseHelper returnDatabase()
{
return mydb;
}
}