I'm doing some big refactoring operations relative to some performance improvements in an android app which is using a class with lot of static variables and even static activity references which are then use through the app ! So I was looking for some best practices in Android to store data and give to these data a global access in my app.
First I removed all the activity references to avoid any memory leak, but I'm still looking to know what is the best practice regarding static variables which need to be used anywhere in the android app.
I read many times (example1, exemple2) : using static variables is not necessary a good practices and it's better/cleaner to use one singleton class with getter and setter to have access to my global variables whatever the activity where I am. So what I've started to think is a class which could looks like this one :
public class AppSingleton extends Application {
private static AppSingleton appInstance;
// different stored data, which could be relative to some settings ..
private String setting1;
private String setting2;
private AppSingleton() {
super();
appInstance = new AppSingleton();
}
public static AppSingleton getAppInstance() {
if (appInstance == null) {
appInstance = new AppSingleton();
}
return appInstance;
}
// Getter and Setter for global access
public String getSetting1() {return setting1;}
public void setSetting1(String setting1) {this.setting1 = setting1;}
public String getSetting2() {return setting2;}
public void setSetting2(String setting2) {this.setting2 = setting2;}
}
Then I can use for example :
// Get the application instance
AppSingleton appS = (App) getApplication();
// Call a custom application method
appS.customAppMethod();
// Call a custom method in my App singleton
AppSingleton.getInstance().customAppSingletonMethod();
// Read the value of a variable in my App singleton
String var = AppSingleton.getInstance().getCustomVariable;
For me AppSingleton sounds good because this singleton which restrics ths instantiation of this class to one object, also this class is not destroyed until there are any undestroyed Activity in the application so it means I can keep my global data in the current lifecycle of my app for example from a 'Log in'. But also I can maintain the state of my global variables from my getters/setters.
But then I also had a look on the official android documentation about Performance Tips which say it's good to use static variable it's faster and don't forget to avoid internal getter and setter it's too expansive !
I'm a bit confused about all of these and I'm really keen to learn more about that topic. What is the best practices about using one class to provide an access to some variables which are needed in different part of my code ? Is the class above AppSingeleton is something which could be interesting to use in terms of architecture and performance ?
Is it a good idea to use a singleton pattern for managing global variables in android ?
those lines are completely wrong on your code:
private AppSingleton() {
super();
appInstance = new AppSingleton();
}
public static AppSingleton getAppInstance() {
if (appInstance == null) {
appInstance = new AppSingleton();
}
return appInstance;
}
you cannot instantiate new Application, the Android framework instantiates it. Change to this:
private AppSingleton() {
super();
appInstance = this; // keep ref to this application instance
}
public static AppSingleton getAppInstance() {
return appInstance;
}
Regarding the accessing of global variables. I believe it's more organized to have those singletons somewhere else on your application. The application class have different responsibilities you should not overload it with different tasks. That's OO clean coding.
Also, sometimes there's not that much reason in an Android app to have getters/setters for everything, because u don't need as much access control as in bigger projects. But this should be considered case-by-case about the necessity and not be used a general rule.
So you could for example have it like:
public class Globals {
private static final Globals instance = new Globals();
public static Globals get() { return instance; }
public String value1 = "Hello"
public int value2 = 42;
}
then on your code call as needed:
Log.d(TAG, Globals.get().value1);
Globals.get().value1 = "World";
Log.d(TAG, Globals.get().value1);
Log.d(TAG, "Value2 = " + Globals.get().value2);
Related
I decided to split the last part of that question here into a new question here: https://softwareengineering.stackexchange.com/questions/411738/extension-of-classes-where-to-put-behaviour-how-much-direct-access-is-allowe
If i have a lib and i want to use it, i wrote mostly a own class. This class has one method. In that there is the code how to instantiate the lib/framework. Sometimes there are a few more methods, with them i not only instantiate the class but use it. For example if i want to start a http-server i have there a start-method.
class Container
{
TheLib theLib;
public void init() //or a constructor
{
//some init of the theLib
}
public void start() //
{
theLib.doSomething(...)
theLib.doSomethingmore(...);
theLib.start(...);
}
//important!
public TheLib getTheLib()
{
return this.theLib; //after i started configured it and so on, i want of course use all methods,
which the lib have in some other parts in my application
}
}
But it seems not to be the best solution.
Are there any better solutions, that OO is?
Often i also use only one method, a own class for this seems to be here a big overhead?
Exposing the lib breaks encapsulation? Tell-Dont-Ask is also violated?
Everything depend on what you actually need or how you have access to your 'the lib' instance.
public class Container {
private TheLib theLib;
/* #1: Do you already created the instance before? */
public Container(TheLib theLib) {
this.theLib = theLib;
}
/* #2: Do you need to created the instance each time? */
public Container() {
this.theLib = new TheLib();
}
public void start() {
theLib.doSomething(...)
theLib.doSomethingmore(...);
theLib.start(...);
}
public TheLib getTheLib() {
return this.theLib;
}
public static void main(String[] args) {
/* #1 */
TheLib theLib = ...;
Container container = new Container(theLib);
/* #2 */
Container container = new Container();
/* Continue the flow of your program */
container.start();
container.getTheLib().doSomethingEvenMore();
}
}
Or maybe you actually need only one instance of your 'Container' class. In this case, you should look on how to make a singleton: Java Singleton and Synchronization
Anwser: Often i also use only one method, a own class for this seems to be here a big overhead?
Well, in Java, you cannot do formal programming like in C, so everything line of code that you write, or will be using, has to be in a class of some sort.
If your piece of code is small and don't really need an object, static function might do the work.
I'm searching for a concept to forward an object to subobjects.
Example:
I would like to create log files for several main Objects, that include sub objects (imagine a REST server that would log every single connection by ID).
Creating one big log file is simple ( redirect System.out.println, I already encapsulated that)
Example code:
class SubElementA{
public SubElementA(){
Debugger.debug("I am called, too");
}
}
Application.java
package com.dev4ag;
class Application{
private ElementA elA;
private String prefix;
public Application(String name){
this.elA = new ElementA();
this.prefix = name;
}
public void countUp(){
Debugger.debug(this.prefix+": I will now count up");
this.elA.doSomeStuff();
}
}
ElementA.java
package com.dev4ag;
class ElementA{
private int counter;
private SubElementA subElementA;
public void doSomeStuff(){
counter++;
Debugger.debug("Counter is: "+counter);
}
//Constructor
public ElementA(){
subElementA = new SubElementA();
this.counter = 0;
};
}
SubElementA.java
package com.dev4ag;
class SubElementA{
public SubElementA(){
Debugger.debug("I am called, too");
}
}
Debugger.java
package com.dev4ag;
public class Debugger {
public static void debug(String output){
//Just imagine we would write to a file here ;)
System.out.println(output);
}
}
(it was more easy to write system.out.println than to create a file, just imagine, Debugger.debug would write to a file).
Now I am thinking about a solution to create one Debug output target for each App. I could definitely change debug to not being static and create a debug object within Application.
But is there any way to use this object in the sub classes without forwarding the debug object either through Constructor or setter function, which would mean to have to add an object for the debugger to each class?
What would be the most beautiful solution for that?
Note that this solution might decrease performance a lot and it is pretty dirty way, but some loggers include such data.
But you can use Thread.currentThread().getStackTrace() to get stacktrace like in error and get class and method from where your method was called.
If you are using java9+ then you should probably use StackWalker API instead, especially that it have nice filters and other useful features.
So then you could guess app by class/method names on the stack.
My installer is storing some information in a singleton class during the installation process. Now, I have noticed that in elevated action, the singleton class does not have the same instance. So far, I have not found any workaround/solution so that they share the same instance. So, I have decided to make sure that if anyone wants to get an instance of the singleton, they must call from an unelevated environment. Let's say the singleton looks like the following:
public class InvestigatorReport {
private final List<Report> reports = new ArrayList<>();
private final static InvestigatorReport INSTANCE = new InvestigatorReport();
private InvestigatorReport() {
MyLogger.logInfo(getClass(), "initiating...");
}
public static InvestigatorReport getInstance(Context context) {
if (context.hasBeenElevated()) {
throw new IllegalAccessError(
"this method must be called unelevated!");
}
return INSTANCE;
}
private boolean addReport(Report report) {
return reports.add(report);
}
}
But the problem is, There are some cases when I have to call this add report from an action class that is elevated. So I have tried the following in my elevated action class:
if (context.hasBeenElevated()) {
return (Boolean) context.runUnelevated(new RemoteCallable() {
#Override
public Serializable execute() {
return getInstance(context).addReport(report);
}
});
}
But, as you can see if I am passing the same context object from the elevated action class to the RemoteCallable class so, even though I am running the class unelevated, the context.hasBeenElevated() still returns true.
Is there any other way that I can check the elevation level other than the context? If you have any other better idea on preventing anyone from calling the singleton getInstance() method, I am all ears.
I would use a different pattern. Make all methods of your singleton static and wrap the data access with runUnelevated calls:
public static boolean addReport(Report report, Context context) {
context.runUnelevated(new RemoteCallable() {
#Override
public Serializable execute() {
InvestigatorReport.reports.add(report);
return null;
}
});
}
In that way, you can call the methods from both elevated and unelevated code without having to check anything at the call site.
I got a class Config wich looks like that:
public Class Config {
public static int someIntValue = 0;
public static String someText = "some text";
}
What i want to do now is saving and loading that config and there is also that inital config if there is no need to load another. So the config can change at any point in the programm.
What i came up with was a Singelton like pattern
public Class Config {
public static Config instance;
private int someIntValue = 0;
private int String someText = "some text";
public static Config getInstance(){
if(instance == null)
instance = new Config();
return instance;
}
public void setInstance(Config config){
this.instance = config;
}
//getter/setter
...
}
But in the end it doesnt look like the best approach and im not quite happy with it :/
Maybe you guys can help me out with a usual / "best practice" way to do that.
Best Regards
Made
I would just use java.util.Properties, or some wrapper around it. Another good approach is java bean and something like xstream to save/load stuff.
Usually in Java for configuration use properties files. And then use ResuorseBundle for reading properties.
Your "singleton" is not a Singleton in the conventional sense.
1) Field instance must be private
2) Remove SetInstance method
3) And you should make your singleton thread safe.
If you'd consider avoiding writing the boilerplate code around java.util.Properties, you can have a look at something that does it for you: OWNER API.
It's configurable to tailor your needs and it offers some additional neat features if compared to java.util.Properties (read the docs).
Example. You define an interface with your configuration parameters:
public interface ServerConfig extends Config {
int port();
String hostname();
#DefaultValue("42")
int maxThreads();
#DefaultValue("1.0")
String version();
}
Then you use it like this:
public class MyApp {
private static ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
private MainWindow window;
public MyApp() {
// you can pass the cfg object as dependency, example:
window = new MainWindow(cfg);
}
public void start() {
window.show();
}
public static void main(String[] args) {
// you can use it directly, example:
System.out.println("MyApp version " + cfg.version() + " copyright (c) ACME corp.");
MyApp app = new MyApp();
app.start();
}
}
You can define the cfg object as member instance on the classes where you need, or you can pass the instance to constructors and methods where you need it.
Version 1.0.4 will be released soon and it will include also "hot reload" and many improvements.
I am developping a server application in Java. I need to load some ressources from different sources (XML and a Database). So, i need some advice on how to cleanly implement the loading.
I have a class "ServerX" who create some "Memory" object, it's those objets who'll hold the loaded ressources.
I've found two different way of loading, but both seems dirty.
1
public class ServerX
{
/**
Will hold the houses for further use.
*/
private Memory<House> houses;
public ServerX()
{
houses = new Memory<House>();
loadHouses();
loadXX();
loadYY();
LoadZZ();
Load...
}
private void loadHouses()
{
//Pseudo code
List<House> loaded = loadHousesFromDatabase();
houses.addAll(loaded);
}
private void loadXX();
...
}
But this way, it flood my "ServerX" class.
2
public interface Loader
{
public void loadHouses(Memory<House> toFill);
public void loadXX(Memort<XX> toFill);
public void loadYY(Memort<YY> toFill);
public void loadZZ(Memort<ZZ> toFill);
}
public class SimpleLoader implements Loader
{
//Implements methods.
}
public class ServerX
{
/**
Will hold the houses for further use.
*/
private Memory<House> houses;
public ServerX(Loader loader)
{
houses = new Memory<House>();
loader.loadHouses(houses);
loader.loadXX...
}
}
But this way, i think i fall into the Poltergeist antipattern, because i create a new loader only to do the request to the database/XML file, and then it's garbage-collected.
So, is there another way to do it, or is one of my solutions good enough?
Thanks.
One pattern you can consider is the Service Locator Pattern. An explanation of Service Locator can be found here.
Basically, a service locator is a registry + cache combined to find the resource once and keep it in memory for object retrieval during the lifecycle of the application. Service Locator is mainly implemented using the Singleton pattern.
Your second solution using a Loader interface and multiple implementations (XMLLoader and DBLoader) is good. However, keep the loader and the server decoupled by making the load methods return a new Memory instance instead of passing the memory as a reference. Add a copyAll method in Memory class to copy the contents of one memory into another memory. ( See ArrayList.addAll or System.arrayCopy in javadoc )