去除Android Studio內(nèi)存泄漏警告Do not place Android context classes in static fields; this is a memory leak

當(dāng)你使用單例類時,Android Studio出現(xiàn)了Do not place Android context classes in static fields; this is a memory leak的內(nèi)存泄漏警告。

public class TestManager {
    private Context mContext;

    private TestManager() {
    }

    public void init(Context context) {
        mContext = context.getApplicationContext();
        Log.d("test", "init " + mContext);
    }

    public static TestManager getInstance() {
        return Holder.INSTANCE;
    }

    private static class Holder {
        private static final TestManager INSTANCE = new TestManager();
    }
}
image.png

明明用了context.getApplicationContext()為什么還會出現(xiàn)警告呢?其實(shí)初始化init時傳入Context這種做法是不恰當(dāng)?shù)?,正確應(yīng)該在構(gòu)造方法就傳入Application Context,但是單例類的構(gòu)造方法是是私有的,無法對外傳入Context,怎么辦呢?引用一個全局靜態(tài)的Application Context。
開發(fā)過程中應(yīng)盡量避免傳入Context對象,單例類中的Context對象必須為Application Context,保證在整個應(yīng)用生命周期內(nèi)引用。如下的寫法可以去掉Android Studio內(nèi)存泄漏的警告:

public class TestManager {
    private Context mContext;

    private TestManager() {
        mContext = AppConfigure.getApplicationContext();
    }

    public void init() {
        Log.d("test", "init " + mContext);
    }

    public static TestManager getInstance() {
        return Holder.INSTANCE;
    }

    private static class Holder {
        private static final TestManager INSTANCE = new TestManager();
    }
}

這樣Android Studio就不會出現(xiàn)內(nèi)存泄漏的警告了,當(dāng)然可以不用AppConfigure 類來獲取Application Context,可以通過在自定義Application中聲明一個公共靜態(tài)全局的Context供其他類引用。
AppConfigure 類的代碼如下:

public class AppConfigure {

    private static volatile Application application;

    public static synchronized void configure(Application application) {
        AppConfigure.application = application;
    }

    public static <T extends Application> T getApplication() {
        try {
            if (application == null) {
                synchronized (AppConfigure.class) {
                    if (application == null) {
                        @SuppressLint("PrivateApi") Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
                        Method method = activityThreadClass.getMethod("currentActivityThread");
                        Object localObject = method.invoke(null, (Object[]) null);
                        Field appField = activityThreadClass.getDeclaredField("mInitialApplication");
                        appField.setAccessible(true);
                        application = (Application) appField.get(localObject);
                        if (application == null) {
                            Method method2 = activityThreadClass.getMethod("getApplication");
                            application = (Application) method2.invoke(localObject, (Object[]) null);
                        }
                    }
                }
            }
            // noinspection unchecked
            return (T) application;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public static Context getContext() {
        return getApplicationContext();
    }

    public static Context getApplicationContext() {
        return getApplication();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容