Programing

경고 : 정적 필드에 Android 컨텍스트 클래스를 배치하지 마십시오.

lottogame 2020. 10. 15. 07:20
반응형

경고 : 정적 필드에 Android 컨텍스트 클래스를 배치하지 마십시오. 이것은 메모리 누수입니다 (또한 Instant Run을 중단 함).


Android 스튜디오 :

정적 필드에 Android 컨텍스트 클래스를 배치하지 마십시오. 이것은 메모리 누수입니다 (또한 Instant Run을 중단 함).

그래서 두 가지 질문 :

# 1 startService컨텍스트에 대한 정적 변수없이 정적 메서드에서를 어떻게 호출 합니까?
# 2 정적 메서드 (동일)에서 localBroadcast를 어떻게 보내나요?

예 :

public static void log(int iLogLevel, String sRequest, String sData) {
    if(iLogLevel > 0) {

        Intent intent = new Intent(mContext, LogService.class);
        intent.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW");
        mContext.startService(intent);
    }
}

또는

        Intent intent = new Intent(MAIN_ACTIVITY_RECEIVER_INTENT);
        intent.putExtra(MAIN_ACTIVITY_REQUEST_FOR_UPDATE, sRequest));
        intent.putExtra(MAIN_ACTIVITY_DATA_FOR_VIEW, sData);
        intent.putExtra(MAIN_ACTIVITY_LOG_LEVEL, iLogLevel);
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

사용하지 않고 이것을 수행하는 올바른 방법은 무엇입니까 mContext?

참고 : 내 주요 질문은 호출 메서드가있는 클래스에 컨텍스트를 전달하는 방법이라고 생각합니다.


메소드에 매개 변수로 전달하기 만하면됩니다. Context시작 목적으로 만의 정적 인스턴스를 만드는 것은 의미가 없습니다 Intent.

방법은 다음과 같습니다.

public static void log(int iLogLevel, String sRequest, String sData, Context ctx) {
    if(iLogLevel > 0) {

        Intent intent = new Intent(ctx, LogService.class);
        intent1.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW");
        ctx.startService(intent);
    }
}

질문에 대한 주석 업데이트 : 시작 활동의 컨텍스트 (생성자 매개 변수 또는 메서드 매개 변수를 통해)를 필요한 지점까지 계단식으로 배열합니다.


멤버 필드에 저장하기로 결정한 경우 메서드 / 생성자를 통해 전달 된 컨텍스트에서 context.getApplicationContext ()를 전달하거나 getApplicationContext ()를 호출했는지 확인하십시오.

바보 증명 예제 (누군가가 활동을 전달하더라도 앱 컨텍스트를 가져 와서 싱글 톤을 인스턴스화하는 데 사용합니다) :

public static synchronized RestClient getInstance(Context context) {
    if (mInstance == null) {
        mInstance = new RestClient(context.getApplicationContext());
    }
    return mInstance;
}

문서에 따르면 getApplicationContext () : "현재 프로세스의 단일 글로벌 애플리케이션 객체의 컨텍스트를 반환합니다."

이는 "getApplicationContext ()"에 의해 반환 된 컨텍스트가 전체 프로세스를 통해 유지 될 것임을 의미하며, 따라서 앱의 런타임 동안 항상 거기에있을 것이기 때문에 어디에나 정적 참조를 저장하더라도 상관 없습니다. / singletons 인스턴스화 됨).

많은 양의 데이터를 보유한 뷰 / 액티비티 내부의 컨텍스트와 비교해 보면, 액티비티가 보유한 컨텍스트를 유출하면 시스템이 분명히 좋지 않은 리소스를 해제 할 수 없습니다.

컨텍스트 별 활동에 대한 참조는 활동 자체와 동일한 수명주기를 유지해야합니다. 그렇지 않으면 컨텍스트를 인질로 잡고 메모리 누수를 유발합니다 (이는 Lint 경고의 원인).

EDIT: To the guy bashing the example from the docs above, there's even a comment section in the code about what I just wrote about:

    // getApplicationContext() is key, it keeps you from leaking the
    // Activity or BroadcastReceiver if someone passes one in.

It's just a warning. Don't worry. If you wanna use an application context, you can save it in a "singleton" class, which is used to save all of singleton class in your project.


In your case it does not make much sense to have it as static field but I don't think it's bad in all cases. If you now what are you doing you can have static field that has context and null it later. I am creating static instance for my main model class that has context inside, its application context not activity context and also i have static instance field of class containing Activity that I null in on destroy. I don't see that I have memory leak. So if some clever guy think i am wrong feel free to comment...

Also Instant Run works here fine...


Generally, avoid having context fields defined as static. The warning itself explains why: It's a memory leak. Breaking instant run may not be the biggest problem on the planet though.

Now, there are two scenarios where you'd get this warning. For an instance (the most obvious one):

public static Context ctx;

And then there's the bit more tricky one, where the context is wrapped in a class:

public class Example{
    public Context ctx;
    //Constructor omitted for brievety 
}

And that class is defined as static somewhere:

public static Example example;

And you'll get the warning.

The solution itself is fairly simple: Do not place context fields in static instances, whether that of a wrapping class or declaring it static directly.

And the solution to the warning is simple: don't place the field statically. In your case, pass the context as an instance to the method. For classes where multiple Context calls are made, use a constructor to pass the context (or an Activity for that matter) to the class.

Note that it is a warning, not an error. Should you for whatever reason need a static context, you can do it. Though you create a memory leak when you do so.


If you make sure it's an Application Context. It doest matter. Add this

@SuppressLint("StaticFieldLeak")

참고URL : https://stackoverflow.com/questions/37709918/warning-do-not-place-android-context-classes-in-static-fields-this-is-a-memory

반응형