Reputation: 497
I would like to know whether it's a bad design choice to use a singleton MainAcitivity as in the following:
public class MainActivity extends AppCompatActivity ... {
public static MainActivity mainActivitySingleton;
....
@Override
protected void onCreate(Bundle savedInstanceState) {
mainActivitySingleton=this;
For instance, in many occasions where I need to access the context I use getContext()
, but sometimes (I don't know why) getContext()
returns null
resulting in a runtime exception. I ended up using the mainActivitySingleton
I created instead of getContext()
.
My little finger tells me this is a bad design choice! if it is the case, can anyone explain why?
Upvotes: 0
Views: 2064
Reputation: 22832
Holding a static reference to Activity
object or Context
, is one of the memory leak cases which leads to extra memory consumption then performance lost. If no reference points to an object, then it is marked as a candidate to be garbage collected. When an object is not used anymore in the program but its memory cannot be released by the Garbage Collector, it is considered as a memory leak case. Therefore, in case of static reference to an Activity
, its memory could not be freed after calling onDestroy
method.
If you really want to hold a static reference to an instance of Activity
or Context
, it is recommended to use WeakReference
.
public class MyActivity extends AppCompatActivity {
private static WeakReference<Context> sContextReference;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sContextReference = new WeakReference<>(this);
}
}
Usage:
Context context = sContextReference.get();
.
Better solution to retain a reference to an instance of Context
is to create and hold a weak reference to it in an Application
class. By this way, we sure that only one reference is pointed to the application context during run time of the app.
MyApplication.java
import android.app.Application;
import android.content.Context;
import java.lang.ref.WeakReference;
public class MyApplication extends Application {
private static WeakReference<Context> sContextReference;
@Override
public void onCreate() {
super.onCreate();
sContextReference = new WeakReference<>(getApplicationContext());
}
@Override
public void onTerminate() {
super.onTerminate();
sContextReference.clear();
}
public static Context getContext() {
return sContextReference.get();
}
}
manifest.xml
<application
android:name="path.to.MyApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme.NoActionBar">
...
</application>
Usage:
Context context = MyApplication.getContext();
Upvotes: 3
Reputation: 152
Never do that. That is the bad design pattern. You should not save activity instance as static instance, because that potential memory leak. If you call getContext()
method in fragment instance then you should call getContext()
in this lifecircle onActivityCreated()
method.
Like this:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Context context = getContext();
}
Upvotes: 1