General Android Advice: Global Variables - android

I was wondering what is the best way to handle global variables for android apps. For example, I'm just trying to create a basic login/register system. I've created a user class (that has various attributes like username, password, etc..), so that when we go to the register activity, the User class constructor is called to create a unique user object once all the fields are filled out. I was then thinking of simply having a global arrayList of type User so that I could just loop through all the users on a login attempt.
So far (due to a combined lack of experience in java, and being very new to this android stuff), I haven't been able to implement this successfully. I have a class which I call "globalStuff" which has a bunch of public static variables (i.e. the list of users and current user), which I thought could be accessed from any activity the user navigates to.
There must be a better way to go about this. I've been reading through a few tutorials and a few posts on here, but none address this very basic idea. So what would be the best way to approach something like this?
Thanks for any help!

It's called a static singleton and it looks like this:
public class Global {
private static Global instance = null;
public static Global getInstance() {
if( instance == null )
instance = new Global();
return instance;
}
// additional methods, members, etc...
}
Then you just refer to it in your code as:
Global.getInstance().getUserList();
etc.

Related

Android app with weak reference and singleton

I'm in the process of completely redesigning my Android app. Before, EVERYTHING was in the same class.
So I tried to redraw everything so that the code is clearer apart Admob than the doc advice to put in the Main thread, I separate the different part of my code in class. So I used two technique: I created a songleton that contains variables that I want to have access to constantly,and I call my classes via weak reference.
Here is what it looks like:
For example, the UIManager class that needs to update the game's IU have a weak reference looks like this:
private static SoftReference<UIManager> ManageUI;
static{ManageUI= new SoftReference<>(null);}
static UIManager get()
{
if(ManageUI.get()==null)
{
ManageUI= new SoftReference<>(new UIManager());
}
return ManageUI.get();
}
GameManager Manager=GameManager.getInstance();
to be able to use the findviewbyid for example I place in method argument the main class that is the mainthread
the singleton that contains all my variables that I want to have permanent access to looks like this:
private GameManager()
{}
/** Holder */
private static class Manager
{
/** Instance unique non préinitialisée */
private final static GameManager instance = new GameManager();
}
/** Point d'accès pour l'instance unique du singleton */
public static GameManager getInstance()
{
return Manager.instance;
}
To separate all in different class, I pass argument to my method so I can call au stuff belong to Activity like that:
(My main class is called GamePlay)
void OpenGlobalScene(GamePlay activity)
{
Manager.OnTitle=false;
if (!checkLayout(activity,R.id.globalscene)) {
LayoutInflater(activity,9, true);
LinearLayout GamePlan = (LinearLayout) activity.findViewById(R.id.globalscene);
GamePlan.setAlpha(Manager.AlphaBord);
}
}
For now, I have not noticed any problems except a few slownesses on old android phone 4.4.2.
Also compared to my old code were EVERYTHING was in the same class, it's much easier to change pieces of code (going to the inapp billing V3 was simpler since everything was in one class that I call like the others with weak referencre)
My questions are:
-What are the problems that such a structure might pose?
I had also chosen that structure to not load or leave in memory things that are not useful
-How are chance that Android will erase from memory an action in progress called with weak reference?
-As you can see I pass the activity has argument to the method, sometimes I pass it from a method to another. Is that fact can cause some trouble?
Thank you for your help.
Check Dagger2 is better than the clasic singleton https://developer.android.com/training/dependency-injection/dagger-android?hl=es-419
thanks for your answer and your tips. I'am gonna check this out.
Anyone else know something about consequences on memory when using weak references ?

android - Headless Retained Fragment vs. Class with public static variables (Global Class)

I'm part of an Android project that uses a global class that contains public static variables, like the example below:
public class Globals {
public static MyObject variable = "this is a test";
}
In the middle of using the application, this global variable's value will be changed let's say:
#Override
public void onCreate(Bundle savedInstanceState) {
Globals.variable = new MyObject(somethingHere);
}
And I came across using Headless Retained Fragments from these blog posts:
http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
http://www.vogella.com/tutorials/AndroidFragments/article.html#headlessfragments
Problem:
I need to have a reference of an initialized object all over the application.
Question:
which is better to implement, a good practice, and practical? Or is there another way I could store a reference of an object all over the application?
The global class has been used over the project, and works fine, but are there any downsides of this implementation?
are there any downsides of this implementation?
Memory leaks, depending on what you are storing there. Leaks are why static data members are considered poor form in classic Java, even if we tend to use them more in Android app development.
Also, this data needs to be considered a cache, one that has to be able to be lazy-created on first access. Your process can be terminated at any point (wiping out the static data member) and the user can return to any activity in your app (courtesy of the recent-tasks list). If you want this data to survive process termination, the most likely solution will be to persist it in a file, database, or SharedPreferences.
All that being said, a retained fragment is a per-activity solution, not a per-application solution, and so it is not a valid alternative for your scenario AFAICT.

How do I share common functions and data across many activities in a single android application

I am looking for how to share functions and data across multiple activities within a single application. I researched the daylights out of it and find some ideology war between overriding the extend for the application and doing a singleton, neither of which I can find examples sufficient to make me understand. Basically I want to share data and share functions. All activities need the same functions and data so this is not one activity sharing data with another activity. It is all activities needing to have access to the same functions and data.
What I want to know is what is the way to go and how do I do it. I need to see what I need to do in my 34 activities, what the class that is going to be common looks like, and what the Manifest entry needs to be. I also need to be sure the common data area will not be closed by the OS.
This is my first Android - Java program and now find my 15,000 line, 34 activity application needs some structure. I know, should have done things differently but the app works really well with two exceptions. One is that it is structurally a mess. Two is that the fact it is a mess is making it hard to fix one behavior I would like to fix.
This is a GPS based application for racing sailboats. It is timing critical and every activity basically runs a once a second loop inside the location manager onLocationChanged function. That part is fine and I do not want to put the GPS code in one place. The problem is that most activities need to filter the data so a lot of code is copied and pasted to the activities. The filter needs history so it needs to remember a state. There are other functions that are used by several activities so these have been copied as well. Think of a function that averages the last three GPS speed readings. It needs to save some history, do its thing, and give a result. All activities need to do the exact same thing. All this works but the problem is that the averaging starts over every time I switch activities because every activity has its own filter. That gives a glitch in the data that I need to get rid of. I need common place to save the data and hopefully a common place to run the filtering and other functions that are common. If every activity can call the filter function that is using common state data, there will be no glitch across activity changes.
I would appreciate some guidance.
Why you don't just make a Class with only static functions, passing needed Parameters? An example if you want to show an ErrorDialog
public class SharedHelper{
public static Dialog showErrorDialog(Context ctx, String message, String title, DialogInterface.OnClickListener okListener, DialogInterface.OnClickListener cancelListener){
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setMessage(message).setTitle(tilte);
if (okListener != null){
builder.setPositiveButton(R.string.button_positive, okListener);
}
if (cancelListener != null){
builder.setNegativeButton(R.string.button_negative, cancelListener);
}
return builder.show();
}
}
Singletons are (from my point of view) one of the uglyest design pattern and will bite you sooner or later. Putting anything in Application requires you to cast it everytime to the Special Application class you designed. A class with only statics however is very flexible in its usage and doesn't need an instance to work.
For the storage-issue:
lookup "SharedPreferences" & "SQLite" and decide afterwards which storage-type suits your needs more.
For the methods-issue:
This question is a bit more complex and there are different ways to do it. For example you could write a parent-class that implements all your globally needed questions and you let all your activity-classes inherit from it.
public class MyParentActivity extends Activity {
public void myMethod() {
}
}
and:
public class Activity1of34 extends MyParentActivity {
myMethod();
}
I think what this comes down to is not an Android problem but an Object-Oriented Programming problem. If I understand the situation correctly, I'm betting the best solution would be to take your shared filter and create a new Filter class that is instantiated within each Activity (this is likely more manageable than a singleton, but not having seen your use case, it's hard to say for sure). If you need to centrally track the averaging, you can simply create a static variable within the Filter class that maintains the same value during the life of the application. If you really want to maintain that average (even past the application's current lifecycle), you can persist it in a database or other local data options. However, I don't see any reason to put everything in a singleton just to maintain that average. Singletons (and all static data structures) can be potentially troublesome if used incorrectly.
I, for one, do not mind the singleton pattern. Of course as everything else it should not be abused.
This is the construction I use for my shared objects. My app is divided into modules this way but can just as well be used in your case.
public class SharedDataObject {
private Context context;
private static SharedDataObject instance;
public static SharedDataObject getInstance() {
if (instance == null) throw new RuntimeException("Reference to SharedDataObject was null");
return instance;
}
public static SharedDataObject createInstance(Context context) {
if (instance != null) {
return instance;
}
return instance = new SharedDataObject(context.getApplicationContext());
}
// notice the constructor is private
private SharedDataObject(Context context) {
this.context = context;
}
...
public void myMethod() {
// do stuff
}
}
Notice that it uses the application context, that means among other things, means that the context owned by SharedDataObject cannot be used for GUI operations. But, the context will live for the entire lifetime of the application, which is nice.
Furthermore I hate having to pass a context everytime I wish to call methods on my SharedDataObject, thus I have a splashscreen calling SharedDataObject.createInstance() on all my modules.
Once an instance is create, I can call:
SharedDataObject.getInstance().myMethod();
Anywhere in my code, regardless of a context being present or not (from the place calling this code that is).

Is a "Globals" class holding static variables in Android safe?

Can anyone enlighten me about the safety of a class holding global values in Android?
Here's a short example of what I mean:
public class Globals {
public static int someVariable = 0;
public static User currentUser = null;
public static Handler onLogin = null;
}
Then somewhere in an Activity I do the following:
Globals.someVariable = 42;
Globals.currentUser = new User("John", "Doe");
I have to rely on Globals.currentUser at multiple places in my app as soon as the user is logged in, but I'm unsure if I should do it, and also if I could use a Handler like this.
I read everywhere that an Android app could be killed anytime, does this mean it is killed completely or maybe just a part of it, thus killing my Globals class only?
Or is there any other way to store globally available data in a safe way, without writing every member change to the database (in fact, my User class is a little more complex than in this example. ;-)
Thanks for your effort!
Edit: Ok, here's what I finally did:
public class MyApp extends Application {
private static MyApp _instance;
public MyApp() {
super();
_instance = this;
}
public static MyApp getContext() {
return _instance;
}
....
private User _user = null;
public User getUser() {
if (_user == null) _user = new User();
return _user;
}
}
Then modify the AndroidManifest.xml and add android:name=".MyApp" to your application node to tell the app to use your subclass.
So far everything works fine and I can easily access the current Context (f.ex. in SQLiteOpenHelper) by calling MyApp.getContext().
It would be better to use the Android Application class. It's meant to store global application state
http://developer.android.com/reference/android/app/Application.html
Just create a subclass and make sure to update your manifest file to use your version. Then you can store whatever you need to in it. Activities have a method getApplication() which you can cast to your class to access your implementation
The pattern is discouraged--you will run into problems when unit testing.
Can you explain how you unit-test a class that must supply different custom "Users" here? You are either forcing a mock/fake class into "User" which will probably have a cross-effect on other tests or you are putting an if(test) into your code which gets ugly quick.
Over time populating this class artificially for testing gets more complex and starts to have relationships and dependencies.
More simply it makes it difficult to unit test a class in isolation.
It's one of those patterns that a given programmer either doesn't see a problem with or never uses because he's been burnt--you'll see little middle ground.

Where should I put global methods and variables in an Android app?

When I'm writing a method or using a member variable, I often find I need to share them across an app. But where should they go?
I can subclass Activity, but that falls over as soon as I use a MapView and am forced to use MapActivity, so not all my activities inherit from my subclass. Is there I way around this?
Where inheritance isn't applicable, I am tending to put generic methods and member variables into a subclass of the Application object, but I'm finding it's creating a mess of code as every class needs to either grab access to the application object through via context, or I have to pass it down.
I suspect I would be better off creating MyApplication.getInstance() and keeping everything in a singleton, instead of passing the application object down through the app classes. but before I wanted to see what you guys had to say.
If you want to access the "Global Singleton" outside of an activity and you don't want to pass the Context through all the involved objects to obtain the singleton, you can just define, as you described, a static attribute in your application class, which holds the reference to itself. Just initialize the attribute in the onCreate() method.
For example:
public class ApplicationController extends Application {
private static ApplicationController _appCtrl;
public static ApplicationController getAppCtrl()
{
return _appCtrl;
}
}
One example with resources: Because subclasses of Application also can obtain the Resources, you could access them simply when you define a static method, which returns them, like:
public static Resources getAppResources()
{
return _appCtrl.getResources();
}
For global methods, use a static Util class with static methods. If you can't use static methods, then the methods shouldn't be global in the first place, and put them in the class that makes sense.
First read this:
How to declare global variables in Android?
Now why you shouldn't use a static singleton. Using a singleton is a the same thing as a global variable. Global variables reduce your maintainability because everywhere you use the global variable you break modularity or introduce global details and assumptions about your overall design. Your program can't have two of these variables because it only looks in one place for it. This means your program can't adapt easily when you have two instances instead of one.
For example, say I have a method called playTurn() and I implement it like so:
public void playTurn() {
globalPlayer.incrementClock();
globalPlayer.doSomething();
globalPlayer.doSomethingElse();
}
Now let's say I want to add a second player to the mix. Uh oh my playTurn() method assumes one player only when it used globalPlayer. If I want to add a second player to the program I have to change that method. Do this a lot and your program is very rigid and inflexible to change. Instead what if I did this:
public void playTurn(Player player) {
player.incrementClock();
player.doSomething();
player.doSomethingElse();
}
Now can do this:
playTurn( player1 );
playTurn( player2 );
I can reuse playTurn() for both player1 and player2 and I didn't have to change it. I just had to change the client of that method.
Most of the time you're being lazy and you want to get a reference to some object, and global variables are fast ways to get references to well known objects. Instead it's better to have one class that resolves the dependencies across your application at start up or the time when it makes sense. Then only that one place understands how your code is put together. For example,
public class Game {
Player player1;
Player player2;
Board board;
public void startGame() {
BlueTooth blueTooth = BlueTooth.getChannel();
player1 = new LocalPlayer();
player2 = new NetworkedPlayer( blueTooth );
board = new Board();
player1.setOpponent( player2 );
player1.setBoard( board );
player2.setOpponent( player1 );
player2.setBoard( board );
}
}
Now everyone has their dependencies, and they don't need to use static variables to find references to things. Also player1 doesn't have to know about details like that player2 is over the network, or that it's apart of a Game. What's important to note is that these objects we're connecting have a long life, possibly the entire program, but if they need to create other things at runtime that's ok for them to do.
Say for example, we need to create multiple players at runtime based on who joins the game. Well we might create a PlayerManager that we can instantiate at startup then create Player objects on the fly. PlayerManager is just a plain old object that we create in Game when we start a new game.
I hope you can start seeing this is a much better way to develop software. You might not understand it right off, but if you think about it will make more sense. It's very subtle change, but very powerful.

Categories

Resources