2016-12-31 1 views
3

Singleton 클래스에서 응용 프로그램 리소스 (구체적으로 문자열 리소스)에 액세스하려고합니다. Singleton이기 때문에이 클래스는 (메모리 누수를 방지하기 위해) Context 객체에 대한 참조를 가질 수 없다. 나는 그물에 다른 구현을 찾고있는 동안, 나는이 두 가지 구현 건너 온 :정적 참조없이 컨텍스트 사용

  1. 는 응용 프로그램 클래스의 정적 컨텍스트를 생성하고 응용 프로그램을 통해 그것을 사용할 수 있습니다.
  2. 매개 변수로 컨텍스트를 필요한 메서드에 전달합니다.

Context 객체에 대한 정적 참조를 사용하므로 주먹 1을 사용하고 싶지 않습니다. 안드로이드의 Application 클래스에서 정적으로 사용하는 것이 좋지만 여전히 해킹처럼 보입니다.

싱글 톤의 someOtherMethod에 전달할 수있는 컨텍스트의 인스턴스가 없으므로 두 번째 구현은 쓸모가 없습니다.

그래서 싱글 톤 인스턴스를 초기화 할 때 내 싱글 톤 추상화를 사용하여 컨텍스트 (예 : getString(int resId)의 코드를 필요로 함)를 재정의했습니다.

지금 메모리 누수가 발생할 수 있는지 궁금합니다. 나는이 방법으로 혼란 스러워요

:

- 재정의 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

이 문자열을 사용하는 방법을 공유 할 수 있습니까? 더 구체적으로 말하면, 컨텍스트를 사용하지 않는 이유는 무엇입니까? 대부분의 경우, Activity/Service/BroadcastReceiver/SQLiteOpenHelper/등은 컨텍스트를 제공하여 싱글 톤을 다소 불필요하게 만듭니다. – chessdork

+0

Android 게임을 사용하고 Google Play 게임 서비스를 사용 중입니다. 앱 전체에 단일 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'은 비동기식 무언가를하고 있습니다.'Context'가 갑자기'null'을 얻는다면, 에러를 던질 것입니다, 그렇지 않습니까? –

+0

@AnkitMundada 컨텍스트가 null이되면 더 이상 컨텍스트와 관련이 없습니다. 리소스에 대해 컨텍스트가 null 인 경우 null을 반환 할 수 있습니다. –

+0

당신의 첫 번째 메소드에서'onResume()'문맥을 깨끗이하지만 여전히'Singleton'의 비동기 호출에 의해 사용된다면 예외가 발생하지 않을까요? 아직도 '비동기 프로세스'에서 여전히 사용된다면 '당신은 더 이상 상황과 관련이 없습니다'라고 말하는 이유는 무엇입니까? –