Is it correct to use static method for getting instance of the Application successor in Android. I have seen this approach in a few open source projects: VLC and Shuttle
public class MyApplication extends Application {
private static MyApplication sApplication;
public static MyApplication getInstance() {
return sApplication;
}
#Override
public void onCreate() {
super.onCreate();
sApplication = MyApplication.this;
}
}
Yes. This approach is correct. This is singleton pattern you are following. As static variable is the right way always, since its the single state you want to maintain everywhere.
Also it is safe, as long as your application never runs in multiple processes. there's a strict one to one ratio of application per process.
I am also using this in my all applications.
Related
I have an android application
#HiltAndroidApp
class MyApp extends Application {
static MyApp app;
static MyApp getApp() {
return app;
}
#Override
public void onCreate() {
super.onCreate();
app = this;
}
}
and I am trying to use it inside a class
class AppStateUsingClass {
public void mymethod() {
MyApp app = MyApp.getApp();
//use app
}
}
Now I can access the app where I don't have the context but I am not sure if its correct way of doing.
My understanding is that the application life cycle is through out app start and stop, therefore its lives as a Singleton so it shall be fine but not sure.
Isn't there any simpler cleaner API to access app, I have app state in MyApp class which I would like to access where context is absent?
Any suggestions are highly appreciated?
What you are doing is a fairly common pattern, and shouldn't really cause problems.
The application class can be treated as a singleton that is alive as long as any part of your application is alive.
The docs specifically state that this class is used to hold application state.
However, depending your actual design, the kind of state information you want to hold and where you want to access it, you may want to create your own singleton, independent of the application class and use that.
Or, you may want to initialize your AppStateUsingClass with a state object passed in the constructor.
This is a design decision, and if you want more opinions on it, create a working code example and post it on https://codereview.stackexchange.com
I have this code that initializes Calligraphy default configuration.
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
// The initialization I want to move
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/MyFont.ttf")
.build()
);
}
}
I want to use Dagger 2 in my project but I don't fully understand what classes should I create and where to move this code in order to keep the project clean ?
In short, you probably wouldn't move anything. The problem with this library is that it uses static methods for initialization and utilization. Static methods are a pain when trying to do dependency injection.
The Library (or why you would not change anything)
It looks like this library is 'just' about switching the used fonts by wrapping the context. As such it does not really provide business logic to your project, but just adds to your views / UI.
Injecting a dependency rather than just calling static methods is most useful if you either want to be able to unit test (inject mocks) or easily swap modules / behavior. In the case of globally changing fonts, both seems less likely.
If on the other hand you really need (or want to) be able to test it, or just have a clean design...
...wrap it
Static methods are a pain, because you can not have objects holding the logic. Unless you wrap them. To properly do DI with static methods, you would have to define your own interface.
public interface CalligraphyManager {
/**
* Called on app start up to initialize
*/
void init();
// other methods, like wrapping context for activity
Context wrap(Context context);
}
You now have some manager to access the static methods. The implementation should be fairly simple, since you want to do proper DI the application context and path needed for init() would be passed into the constructor of your implementation. The creation of your manager can thus be handled by your ApplicationModule—just add some provides method
#Singleton
#Provides
// You would also have to provide the path from somewhere or hardcode it
// left as an exercise for the reader
CalligraphyManager provideCalligraphyManager(Context context, String path) {
return new ActualCalligraphyManager(context, path);
}
Your application would then look something like this:
public class MyApplication extends Application {
#Inject
CalligraphyManager mCalligraphy;
#Override
public void onCreate() {
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
mComponent.inject(this);
// call the initialization
mCalligraphy.init();
}
}
Everything else is as usual. You have a singleton object in your application components graph, you can thus inject the same object into your activities and call `wrap´ where appropriate.
What about testing / mocking?
Since the whole reason of doing this is to make it 'testable', you can now easily provide a mock / stub object.
Create another implementation of the manager where init() would just do nothing, and wrap(Context) would just return the same context—a simple stub object.
I have developed a habit of taking a shortcut in programming, and I am wondering what the consequences are:
In MainActivity() declare:
public static Context xt;
In the MainActivity constructor of MainActivity
xt = this;
In my Renderer constructor:
readTextFile(MainActivity.xt, R.raw.vertexcode);
and the function readTextFile uses context to open resources
public static String readTextFileFromRawResource(final Context context,
final int resourceId)
{
final InputStream inputStream = context.getResources().openRawResource(
resourceId);
. . .
Your implementation is bad, for me the bes use static variables is using Singleton.
Singleton Pattern
Now, remember if you are using reference object for the Context, probably some methods could be alter the variable, and others function can suffer the consequences.
Tavian Barnes gave you a tip use a custom Application subclass. Its my technique on android apps and working great. Activities and in-process services can use it. Application instance is a system automanaged singleton, all apps have either default or custom one. I use it for app-global things.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.app"
android:versionName="1.0" android:versionCode="3" >
<application
android:name=".MyApplication"
...
</application>
</manifest>
com.my.app.MyApplication
package com.my.app;
import android.app.Application;
public class MyApplication extends Application {
#Override public void onCreate() {...}
public void doSomething() {
// getApplicationContext() getter is available here
}
}
Use this getter (MyApplication)getApplication() in any activity or inprocess service class.
It's "bad" mainly because there's no guarantee that your MainActivity constructor has been called. This can happen if your process is terminated and then re-created while another activity is above it, for example.
You can use a custom Application subclass and store a static reference to its Context there, which will be available no matter how your app starts. (The exception is that ContentProviders may be instantiated before your Application subclass.) You may want to expose it via a static method instead of a static field.
But it would be better design to simply pass the Context as a constructor parameter to Renderer, if at all possible.
I think will be bad if your Application will lose the values of the static variables when the OS requires more memory, I use the onResume() method to set the value of my static variable context.
public class MyApplication extends Activity{
#Override
protected void onResume() {
MyApplication.context = getApplicationContext();
super.onResume();
}
}
Your implementation is bad. Check Android Developers Blog.
Avoiding memory leaks
http://android-developers.blogspot.jp/2009/01/avoiding-memory-leaks.html
In this case (keep Context in a static field), GC do not release Context Object until the application process is killed. This pattern is so-called memory leak and should be avoid.
I came across a code where a utility class has a static reference of a client of a service. Here is the simplified version of the code
public class MyHelper {
//assume that prime service checks if the number is prime
private static PrimeService client;
public static void setClient(PrimeService client) {
MyHelper.client = client;
}
public static boolean isIntegerPrime(int i) {
return client.isIntegerPrime(i);
}
}
Any thoughts on the design of this class? Apart from accidently setting the client to null, I could not think of any downside of such utility classes with static references of remote service clients. I am interested in knowing the correctness of this class from design perspective.
Your setMethod is of no use as it is not setting the static variabl.
public static void setClient(PrimeService client) {
client = client; //the assignment to this variable has no effect. }
You need to change this to
public static void setClient(PrimeService client) {
MyHelper .client = client;
}
Well, if the client is set before the 1st call of "isIntegerPrime" you would not see any NullPointerExceptions.
You might get problems with parallel access to that client. Thus when synchronization is an issue.
If PrimeService is also under your control and usage like that is ok, it might also be an option to make the method in PrimeService static.
The biggest problem you might run into with this design (aside from concurrent access and the programming error mentioned in Juned's Answer) is that you might share state inadvertently. There is no way that MyHelper can be sure that the passed client reference is not used elsewhere. This might pose an encapsulation problem. Consider the concurrent access problem. Even if you make the method isPrime(int i) synchronized, some other thread might call isIntegerPrime on the PrimeService instance passed to MyHelper.
At many places in my web application I need a certain String which is :
request.getServletContext().getRealPath("/");
// I can only get this once the web-app starts
Sometimes a simple java class needs to know this string. I don't want to pass each and every time this string to the class's function. One way could be to stash this string in a file at the very beginning of the web application. Every time I would need this, simply read the file.But this doesn't seem a pretty good option. Is there any other way out ?
May be I can store in the context.xml of the application. If it is possible how do I do that ?
If there is a better way please suggest.
I am using tomcat as the server.
Invoke run the following code when your application starts (e.g. with a ServletContextListener):
public void contextInitialized(ServletContextEvent sce) {
ServletContextRootRealPath.set(sce.getServletContext().getRealPath("/"));
}
Then later whenever you need it you simply call
ServletContextRootRealPath.get()
Since it's all static the variable is accessible JVM-wide to every code that runs in this JVM.
Utility class
public final class ServletContextRootRealPath {
private static String path;
private ServletContextRootRealPath() {
// don't instantiate utility classes
}
public static void set(String rootRealPath) {
path = rootRealPath;
}
public static String get() {
return path;
}
}
You can store the value in static variable of any class (Basically a helper class which is used for serving common utility functions). Later you can refer to this variable without creating instance of the class, as it is static and can be accessed without its instance.