2016-12-31 6 views
3

Я пытаюсь получить доступ к ресурсам приложений (специфичные для строковых ресурсов) из класса Singleton. Будучи Singleton, этот класс не может ссылаться на объекты Context (чтобы предотвратить утечку памяти). Хотя я искал другие реализации в сети, я столкнулся с этими двумя реализациями:Использование контекста без какой-либо статической ссылки

  1. Создайте статический контекст в классе Application и используйте его в приложении.
  2. Пропустить контекст как параметр метода, который его требует.

Я не хочу использовать кулак, так как он также использует статическую ссылку на объект Контекста. Я понимаю, что это нормально, что он статически включен в класс Application android, но все же выглядит как хак.

Вторая реализация бесполезна, так как у меня нет экземпляра контекста, который я могу передать в someOtherMethod из singleton.

Итак, я придумал следующую реализацию, в которой я делаю свой реферат Singleton, чтобы переопределить его контекст, требующий методов (например, getString(int resId) в коде ниже), когда я инициализирую экземпляр singleton.

Мне любопытно узнать, может ли это привести к утечке памяти сейчас?

Где я путать с этим подходом:

-> Ссылка на контекст, в перекрытом getString является окончательным. Я не уверен, может ли это вызвать утечку памяти или нет.

public abstract class SingletonClass{ 

    . 
    . 
    . 

    private static SingletonClass sInstance; 

    private SingletonClass(Context paramContext) { 
     // constructor code 
    } 

    public static SingletonClass getInstance(final Context context) { 
     if (sInstance == null) { 
      sInstance = new SingletonClass(context){ 
       @Override 
       public String getString(int resId) { 
        return context.getString(resId); 
       } 
      }; 
     } 
     return sInstance; 
    } 

    public abstract String getString(int resId); 

    . 
    . 
    . 

    private void someOtherMethod(){ 
     //uses above getString() 
    } 

    } 
+0

Не могли бы вы рассказать, как вы используете эти строки, а точнее, почему у вас не будет 'Context', когда вы их используете? В большинстве случаев Activity/Service/BroadcastReceiver/SQLiteOpenHelper/и т. Д. Обеспечивал бы контекст, делая ваш singleton несколько ненужным. – chessdork

+0

Я работаю над игрой для Android и использую сервисы Google Play Game. Я думал о синглете, поскольку мне нужно, чтобы один GoogleApiClient поддерживал приложение. –

ответ

0

У вашего подхода есть утечка памяти. Первый контекст, переданный в getInstance, никогда не будет собираться с мусором, так как ваш анонимный класс содержит ссылку на него. (и есть статическая ссылка на анонимный класс). например, если вы вызываете getInstance(Activity), эта активность останется в памяти до тех пор, пока процесс не будет убит!

К счастью, есть довольно легкое решение, чтобы избавиться от утечки памяти. Вы можете безопасно придерживаться контекста приложения (context.getApplicationContext), который в основном представляет собой одноэлементный контекст для жизни приложения.

public static SingletonClass getInstance(Context c) { 
    if (sInstance == null) { 
     sInstance = new SingletonClass(c.getApplicationContext()); 
    } 
    return sInstance; 
} 
0

Вы можете зависеть от жизненного цикла деятельности, и требуют деятельности передать ссылку на ваш единственный объект в методе onResume, и очистить его в OnPause.

protected void onResume() { 
    super.onResume(); 
    Singleton.getInstance().onResume(this); 
} 

protected void onPause() { 
    super.onResume(); 
    Singleton.getInstance().onPause(); 
} 

Кроме того, вы можете обновить экземпляр Context и держать его в WeakReference:

class Singleton { 
    private WeakReference<Context> mContext; 

    private boolean hasContext() { 
    return mContext != null && mContext.get() != null; 
    } 

    public static Singleton getInstance(Context c) { 
    //do your singleton lazy 
    if (!sInstance.hasInstance()) { 
     sInstance.mContext = new WeakReference<>(c); 
    } 
    return sInstance; 
    } 
} 

Второй случай может содержать ссылку на отделочные деятельность, поэтому я не предлагаю его.

+0

Что такое 'Singleton' делает что-то асинхронное.Если «Контекст» внезапно получит «null», это вызовет ошибку, не так ли? –

+0

@AnkitMundada, если ваш контекст имеет значение null, больше не имеет никакого отношения к контексту. Вы можете просто вернуть значение null, если контекст имеет значение null для ресурсов. –

+0

Я имел в виду, в вашем первом методе, когда я очищаю контекст в 'onResume()', но если он все еще используется асинхронным вызовом 'Singleton', не будет ли это исключение? Почему вы говорите: «вы больше не имеете никакого отношения к контексту», если он все еще используется асинхронным процессом? –

 Смежные вопросы

  • Нет связанных вопросов^_^