使用Singleton MainActivity?

时间:2018-12-14 14:20:02

标签: java android singleton android-context main-activity

我想知道使用单例MainAcitivity是否是一个糟糕的设计选择,如下所示:

public class MainActivity extends AppCompatActivity ... {
   public static MainActivity mainActivitySingleton;
   ....
   @Override
   protected void onCreate(Bundle savedInstanceState) {
   mainActivitySingleton=this;

例如,在许多需要访问上下文的情况下,我使用getContext(),但是有时(我不知道为什么)getContext()返回null导致运行时异常。我最终使用了创建的mainActivitySingleton而不是getContext()

我的小手指告诉我这是一个糟糕的设计选择!如果是这样,谁能解释原因?

2 个答案:

答案 0 :(得分:1)

永远不要这样做。这是糟糕的设计模式。您不应将活动实例另存为静态实例,因为这可能会导致内存泄漏。如果在片段实例中调用getContext()方法,则应在此生命周期getContext() method中调用onActivityCreated()

赞:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Context context = getContext();
}

答案 1 :(得分:1)

Activity对象或Context进行静态引用是内存泄漏的一种情况,这会导致额外的内存消耗,进而导致性能下降。如果没有引用指向对象,则将其标记为要进行垃圾收集的候选对象。如果程序中不再使用对象,但是垃圾回收器无法释放其内存,则将其视为内存泄漏情况。因此,在静态引用Activity的情况下,调用onDestroy方法后无法释放其内存。

如果您确实想持有对ActivityContext实例的静态引用,建议使用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);
    }
} 

用法:

Context context = sContextReference.get();

更新:

保留对Context实例的引用的更好解决方案是在Application类中创建并保持对它的弱引用。通过这种方式,我们确保在应用程序运行期间仅一个引用指向应用程序上下文。

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>

用法:

Context context = MyApplication.getContext();