Android Studio global static variable accessible from multiple activities - android

In android studio I want to have a static (unchanging) variable which, I can obtain from multiple activities. My application has several activities:
Login Activity
Home Activity
Sub Activity 1
Sub Activity 2
Sub Activity 3
Within these activities I need to check a value to execute different code depending on the value. In my case it is a device address. I use this device address in two places and therefore, presently define it in 2 separate places. I know this is an incorrect way of doing this. So I want to define it once and access it from both activities e.g. Home Activity and Sub Activity 1.
I want to know where I can define this variable and then how I include it.
An example of the variable is :
private String Device_Address = "XX:XX:XX:XX:XX:XX";
One idea is should I make it a public static variable from the home activity and then import the variable to the sub activity?
Thanks

Declare veriable in Application class
public class App extends Application
{
private boolean isActive= false;
public boolean getisActive() {
return isActive;
}
public void setisActive(boolean _isActive) {
this.isActive= _isActive;
}
}
and Usage is
App.getInstance().getisActive()
Register App in Manifest
<application
android:name=".App"

You can use a global static class for this. You will be able to access the class from anywhere and it's not bound to an activity.
public class Constants {
public static final String DeviceAddress = "XX:XX:XX:XX:XX:XX";
}

The first answer may work for you, but in production (where you will have a lot of persistent data objects, used by several contexts) I recommend to use MVVM pattern and Dagger.
Your activities will have different view models, which can hold a reference to some singleton repository (You will implement it by yourself and inject it to view models with Dagger).
The repository itself will be designed to provide or store data, which can be retrieved from databases, shared preferences and etc. Your variable can be stored there too.

Related

Moving data back and forth between two open activities

I have two activities- act1 and act2. I want to transfer a String from act1 to act2 when the user presses a button and after some computation I want to transfer a LatLng from act2 to act1, while keeping both activities open (or at least be able to restore every change in act2 from the app start).
Things I tried:
I saw here that if I add some flags to the intent I won't start new activities when using startActivity(). It works well getting from act1 to act2 but after starting act1 from act2 it stops act2, so in the next act2 opening it will make a new act2 copy.
I looked at the not-deprecated version of startActivityForResult, but since I need both of the activities open it's not what I want. I also want both of them to receive and return data.
From here, using static data structure in one activity may not be good practice.
I tried using extras and onNewIntent but couldn't make it work (since I can't keep both activities running).
Background (if relevant):
I have an app with two activities- main, which stores a ListView, and a map activity.
The map must have a marker placed in each saved address.
The list has two button types:
"Add a new place...", that open the map activity, and adds a new marker where the user wants.
-some address-, that open the map in the location corresponding to this address.
I need a way to pass the desired address to the map so it'll show this location, and I also need to pass the new saved address back to the main activity after creating a location.
You can use the repository pattern to store the data in a way accessible by all code in your app.
What is a repository?
A repository is a simple class that holds some data and provides access to it. Something like:
class Repository {
private String theString = "";
public void setTheString(String newValue) {
theString = newValue;
}
public String getTheString( {
return theString;
}
}
It's a good idea to give a more descriptive name to the repository. So if this is a repository that stores location data, you could name it LocationRepository.
Where should it be created?
A good place to keep the reference to it is the Application class. If you don't have one, you can define it like this:
class MyApplication extends Application {
private Repository repository = new Repository();
public Repository getRepository() {
return repository;
}
}
It needs to extend the Application class provided by the android framework
You can also override the onCreate() method for more complex initialization, if necessary in your case
Define the application class in the manifest
In order for the android framework to know about your custom Application class you need to define it in the AndroidManifest.xml:
<application
android:name=".MyApplication"
...
Access the repository in your activities
Now in each activity you can cast the application context into your application class:
class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Repository repository = ((MyApplication) getApplicationContext()).getRepository();
System.out.println(repository.getTheString());
}
}
If you want a cleaner approach, where you care about architecture design:
Create a ViewModel per each activity
Create a Singleton, which the ViewModels access, and use it to share the data.
The Singleton could be something like:
object AddressManager{
fun saveAddress(address: Address) {
}
fun getAddress(): Address{
}
}
And of course, I would advise you to use Dagger and Hilt for the injection and not to use "object", but this is again more and more design ideas.

Why extend the Android Application class?

An extended Application class can declare global variables. Are there other reasons?
Introduction:
If we consider an apk file in our mobile, it is comprised of
multiple useful blocks such as, Activitys, Services and
others.
These components do not communicate with each other regularly and
not forget they have their own life cycle. which indicate that
they may be active at one time and inactive the other moment.
Requirements:
Sometimes we may require a scenario where we need to access a
variable and its states across the entire Application regardless of
the Activity the user is using,
An example is that a user might need to access a variable that holds his
personnel information (e.g. name) that has to be accessed across the
Application,
We can use SQLite but creating a Cursor and closing it again and
again is not good on performance,
We could use Intents to pass the data but it's clumsy and activity
itself may not exist at a certain scenario depending on the memory-availability.
Uses of Application Class:
Access to variables across the Application,
You can use the Application to start certain things like analytics
etc. since the application class is started before Activitys or
Servicess are being run,
There is an overridden method called onConfigurationChanged() that is
triggered when the application configuration is changed (horizontal
to vertical & vice-versa),
There is also an event called onLowMemory() that is triggered when
the Android device is low on memory.
Application class is the object that has the full lifecycle of your application. It is your highest layer as an application. example possible usages:
You can add what you need when the application is started by overriding onCreate in the Application class.
store global variables that jump from Activity to Activity. Like Asynctask.
etc
Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
For example, if you want to get the basic authentication data for each http request, you can implement the methods for authentication data in the application object.
After this,you can get the username and password in any of the activities like this:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
And finally, do remember to use the Application object as a singleton object:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
For more information, please Click Application Class
Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.
I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.
The Application class is a singleton that you can access from any activity or anywhere else you have a Context object.
You also get a little bit of lifecycle.
You could use the Application's onCreate method to instantiate expensive, but frequently used objects like an analytics helper. Then you can access and use those objects everywhere.
Best use of application class.
Example: Suppose you need to restart your alarm manager on boot completed.
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
Not an answer but an observation: keep in mind that the data in the extended application object should not be tied to an instance of an activity, as it is possible that you have two instances of the same activity running at the same time (one in the foreground and one not being visible).
For example, you start your activity normally through the launcher, then "minimize" it. You then start another app (ie Tasker) which starts another instance of your activitiy, for example in order to create a shortcut, because your app supports android.intent.action.CREATE_SHORTCUT. If the shortcut is then created and this shortcut-creating invocation of the activity modified the data the application object, then the activity running in the background will start to use this modified application object once it is brought back to the foreground.
I see that this question is missing an answer. I extend Application because I use Bill Pugh Singleton implementation (see reference) and some of my singletons need context. The Application class looks like this:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
#Contract(pure = true)
#Nullable
public static Context getAppContext() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
And the singletons look like this:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
#Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
#SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
This way I don't need to have a context every time I'm using a singleton and get lazy synchronized initialization with minimal amount of code.
Tip: updating Android Studio singleton template saves a lot of time.
I think you can use the Application class for many things, but they are all tied to your need to do some stuff BEFORE any of your Activities or Services are started.
For instance, in my application I use custom fonts. Instead of calling
Typeface.createFromAsset()
from every Activity to get references for my fonts from the Assets folder (this is bad because it will result in memory leak as you are keeping a reference to assets every time you call that method), I do this from the onCreate() method in my Application class:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
Now, I also have a method defined like this:
public static App getAppInstance() {
return appInstance;
}
and this:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
So, from anywhere in my application, all I have to do is:
App.getAppInstance().getQuickSandRegular()
Another use for the Application class for me is to check if the device is connected to the Internet BEFORE activities and services that require a connection actually start and take necessary action.
Source: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
In many apps, there's no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
Specialized tasks that need to run before the creation of your first activity
Global initialization that needs to be shared across all components (crash reporting, persistence)
Static methods for easy access to static immutable data such as a shared network client object
You should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
To add onto the other answers that state that you might wish store variables in the application scope, for any long-running threads or other objects that need binding to your application where you are NOT using an activity (application is not an activity).. such as not being able to request a binded service.. then binding to the application instance is preferred. The only obvious warning with this approach is that the objects live for as long as the application is alive, so more implicit control over memory is required else you'll encounter memory-related problems like leaks.
Something else you may find useful is that in the order of operations, the application starts first before any activities. In this timeframe, you can prepare any necessary housekeeping that would occur before your first activity if you so desired.
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
You can access variables to any class without creating objects, if its extended by Application. They can be called globally and their state is maintained till application is not killed.
The use of extending application just make your application sure for any kind of operation that you want throughout your application running period. Now it may be any kind of variables and suppose if you want to fetch some data from server then you can put your asynctask in application so it will fetch each time and continuously, so that you will get a updated data automatically.. Use this link for more knowledge....
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android

In android , how to make array list available to one or more activities?

I have one activity called mylikes , it can be called from main activity then it should display the liked items list. Another activity called programs have list of items where i press the like button and it should add that item to liked item list and display in Mylike activity.
I am adding that item to array in program activity but when i call the mylike activity from main, i am getting force close error.So how to make array list global.
You can override the default application class with your own and create and use your array from there. If you have an application called MyApplication then add a class
public class MyApplication extends Application {
public ArrayList myGlobalArray = null;
public MyApplication() {
myGlobalArray = new ArrayList();
}
}
For adding the data to array use :
((MyApplication)getApplicationContext()).myGlobalArray = anyarray;
You can then access in an activity via something like
((MyApplication)getApplicationContext()).myGlobalArray ... etc.
In your application manifest you also need to name your extended application class by adding the name to your application block
<application
android:icon="#drawable/icon"
android:name=".MyApplication" ...
If you have a globally scoped complex object that all activities need to access and you don't want to serialize/deserialize that's the easiest way IMO, for simpler scenarios you can pass items when you start the activity by putting extra's into the intent
You can also use singletons, but the application class is pretty easy to manage
I did not test or compile code, this is just intended as an overview so watch out for typos etc.
Here is the link for the Application class doc's Application
You can use some singleton class to hold your likes array, to share this list cross multiple activities.
public class LikeManager{
List<Item> likes;
//....
private LikeManager(){
//...
}
public LikeManager getInstance(){
//...
}
public List<Item> getLikes(){
return likes;
}
}
So, when you need access likes, call LikeManager.getInstance().getLikes()
The simplest method would be to have public getters and setters that allow other parts of your app to retrieve and set the values of the ArrayList.
Barring that, you could write it to the SharedPreferences, a file somewhere or store the data in a database.
You can use Application class to store this data and you can use it across all the Activity
public class BusinessClass extends Application
{
public ArrayList array = new ArrayList();
}
Then call it in any activity using following code
BusinessClass appState = ((BusinessClass)getApplicationContext());
ArrayList myarray=appState.array;
In android if you want to maintain any thing global and share it across two or more activity then you can use Application calss.
For more info
http://developer.android.com/reference/android/app/Application.html

Using static instead of parcelable/serialize -- is this bad?

I need to keep a reference to an object between different activities. The two said mentions seem to create new objects from activity to activity. This is a problem because changes to the object in the "child" activities don't persist once the parent activity gets focus. My solution to this was just to create a static getter in the parent-most activity which the child activities call and work with. Is this the incorrect way to go about this?
If you want to share a single instance of an object between activities, you can create a singleton class. The only thing wrong with using your parent-most activity class to implement the singleton might be that it might violate the single responsibility principle.
You can make your object persistent throughout the whole application lifecycle by making it a field in your Application-derived class.
public class MyAppication extends Application {
private Object mMyData;
public setData(Object data) {
mMyData = data;
}
public Object getData() {
return mMyData;
}
}
Then ((MyApplication)getAppllication()).setData or getData()
This way you can exchange data within the application because MyApplication will always exist.
You'll also have to add MyApplcation to manifest
You should create a Singleton, this has a single instance whenever you talk to it. (Just like your describing).
Here's one I made earlier : https://stackoverflow.com/a/6539080/413127

how to avoid that a class gets unloaded during lifecycle

I would like to use a class and its class variables as a global "cache" for my globally used variables.
I need to ensure that it never gets unloaded during the app livecycle and loses its values.
How can I ensure that the class never gets unloaded?
This is how the class is declared:
public class GlobalVars {
public static Integer gi1;
public static WebiDBAdapter gDBAdapter;
}
Many thanks!
Use the Application class
Base class for those who need to maintain global application state. You can provide your own implementation by specifying its name in your AndroidManifest.xml's tag, which will cause that class to be instantiated for you when the process for your application/package is created.
public class ApplicationGlobalVars extends Application
{
public Integer gi1;
public WebiDBAdapter gDBAdapter;
// put some setter and getters here.
public Integer getGi1()
{ return gi1; }
}
To use it in your activities :
ApplicationGlobalVars appState = ((ApplicationGlobalVars)this.getApplication());
appState.getGi1();
If you want to store global objects that can be accessed by ANY client, you should look into using Application State. For example, application state is often used to implement a global counter that tracks how many times an operation has been performed by ALL the application's clients.
If, however, you need to store separate global state for each client, then Session State would be your best choice.

Categories

Resources