활동 컨텍스트 또는 애플리케이션 컨텍스트를 언제 호출해야합니까?


265

이 두 문맥이 무엇인지에 대해 많은 글이 게시되었습니다. 그러나 나는 여전히 그것을 제대로 이해하지 못하고 있습니다.

내가 지금까지 이해 한 것처럼 : 각각은 클래스의 인스턴스이므로 일부 프로그래머는 this.getApplicationContext()메모리를 "누설"하지 않기 위해 가능한 한 자주 사용하는 것이 좋습니다 . 이는 다른 인스턴스 this( Activity인스턴스 컨텍스트를 얻는 ) Activity가 사용자가 전화를 기울이거나 앱을 떠날 때마다 파괴되고 있는 것을 가리 키기 때문입니다. ..

그러나 누구나 사용할 수있는 올바른 코딩 예제 this(현재 Activity인스턴스 의 컨텍스트 가져 오기) 를 사용 하여 응용 프로그램 컨텍스트가 쓸모 없거나 잘못 될 수 있습니까?

답변:


408

getApplicationContext()거의 항상 잘못되었습니다. 양 Hackborn (다른 사람의 사이에서)는 매우 명시 적이었다 에만 사용 getApplicationContext()당신이 알고있을 때 당신이 사용하는 getApplicationContext()단지 당신이 할 때 필요 사용 getApplicationContext().

무딘, "일부 프로그래머"사용 되려면 getApplicationContext()(또는 getBaseContext()자신의 자바 경험이 제한되기 때문에 낮은 정도를,). 그들은 (예를 들어, 한는 내부 클래스를 구현 OnClickListenerA의 Button에서 Activity)와이 필요합니다 Context. MyActivity.this외부 클래스에 도달 하는 데 사용 하는 대신 ' 또는 객체 를 this사용 합니다.getApplicationContext()getBaseContext()Context

당신 은 당신이 당신의 처분에 있을 가능성 이 다른 어떤 것보다 오래 살 수있는 무언가를 필요로 알고있는 경우 에만 사용 합니다. 시나리오는 다음과 같습니다.getApplicationContext()ContextContext

  • 그 자체에 getApplicationContext()묶인 무언가가 필요한 경우 사용 하면 Context전역 범위를 갖습니다. 내가 사용 getApplicationContext(), 예를 들어, WakefulIntentService정적을 위해, WakeLock서비스에 사용되는. 그 이후 WakeLock정적, 그리고 내가 필요 Context로 얻을 수 PowerManager를 만드는, 그것은 사용하기 가장 안전하다 getApplicationContext().

  • 를 통해 인스턴스 간에 (즉, 바인딩에 대한 핸들)을 전달하려는 경우 에서에서 getApplicationContext()바인딩 할 때 사용 합니다 . Android는이를 통해 바인딩을 내부적으로 추적하고 바인딩 을 생성하는 참조를 보유 합니다. 당신이에서 결합하면 , 새로운 인스턴스에 대한 참조해야합니다 이전에 암시 적 참조가 , 그리고 기존의 캔은 쓰레기 수집 할 수 없습니다.ServiceActivityServiceConnectionActivityonRetainNonConfigurationInstance()ServiceConnectionsContextsActivityActivityServiceConnectionActivityActivity

일부 개발자 Application는 자신의 전역 데이터 에 대해 사용자 정의 서브 클래스를 사용 getApplicationContext()합니다. 확실히 가능합니다. 당신 만이 할 수있는 것보다 다른 이유가있는 경우 나, 정적 데이터 멤버를 선호 하나의 사용자 정의 Application개체를. 나는 커스텀 Application객체를 사용하여 하나의 앱을 만들었고 고통 스럽습니다. Hackborn 씨도이 입장에 동의합니다 .

어디를 가든지 사용 하지 않는 이유는 다음과 같습니다 getApplicationContext().

  • Context모든 것을 지원 하는 완전한 것은 아닙니다 Activity. 이 작업을 수행하려고 시도하는 다양한 작업은 대부분 GUI와 관련하여Context 실패 합니다 .

  • 발신자 가 정리하지 않은 호출에 의해 생성 된 항목 ContextgetApplicationContext()보유한 경우 메모리 누수가 발생할 수 있습니다 . 를 사용하여 Activity무언가를 보유 Activity하면 가비지가 수집되면 다른 모든 항목도 플러시됩니다. Application객체는 프로세스의 수명 동안 유지됩니다.


1
이 답변에 감사드립니다. 이 답변을 읽기 전에 찾은 다른 링크도 일부 사람들을 도울 수 있습니다. stackoverflow.com/questions/7298731/…- 이 링크는 메모리 누수에 대한 나의 관심사를 설명합니다.
Norfeldt

27
@ Norfeldt : 참고로, 귀하의 의견 링크는이 답변으로 다시 연결됩니다.
CommonsWare

2
감사합니다 .. 이것은 링크 : stackoverflow.com/questions/5796611/… 이것은 이것을 사용하여 얻을 까봐 메모리 누수를 설명합니다
Norfeldt

6
@ djaqeel : 당신의 인용의 후반 부분은 거의 사실입니다. "정적 데이터 멤버와 같이 활동보다 오래 살 수있는 활동에 활동 컨텍스트를 제공하지 마십시오"로 표시하는 것이 좋습니다. 그러나 주어진 상황에서 필요한지 정확히getApplicationContext() 아는 경우 에만 사용하십시오 . 레이아웃 팽창? 활동을 사용하십시오. 구성 변경을 유지하기 위해 바인딩이 필요한 서비스에 바인딩 하시겠습니까? 를 사용 하면 바인딩이 인스턴스에 연결되지 않습니다 . getApplicationContext()Activity
CommonsWare

7
@ 서버 : 나는 이것을 내 대답에 포함시킵니다. Dave Smith는 또한 문맥을 다루는 훌륭한 블로그 게시물을 가지고 있습니다. doubleencore.com/2013/06/context 그의 요약 단락 : "대부분의 경우 작업중인 둘러싸는 구성 요소에서 직접 사용할 수있는 문맥을 사용하십시오. 안전하게 보관할 수 있습니다. 해당 참조가 해당 구성 요소의 수명주기를 넘어서 연장되지 않는 한 참조 또는 활동이나 서비스를 벗어나는 객체의 컨텍스트에 대한 참조를 저장해야하는 즉시 일시적으로도 저장 한 해당 참조를 전환하십시오 "응용 프로그램 컨텍스트로 넘어갑니다."
CommonsWare

48

SDK 사이트에 제대로 문서화되지 않은 많은 것들이 있다고 생각합니다. 이것 중 하나입니다. 내가 할 주장은 응용 프로그램 컨텍스트를 사용하는 것이 기본적으로 더 나은 것처럼 보이고 실제로 필요할 때 활동 컨텍스트 만 사용하는 것 같습니다. 활동 컨텍스트가 필요하다는 것을 본 유일한 장소는 진행 대화 상자입니다. SBERG412는 토스트 메시지에 활동 컨텍스트를 사용해야한다고 주장하지만 Android 문서는 사용중인 애플리케이션 컨텍스트를 명확하게 보여줍니다. 이 Google 예제로 인해 토스트에 항상 애플리케이션 컨텍스트를 사용했습니다. 그렇지 않은 경우 Google에서 공을 떨어 뜨 렸습니다.

생각하고 검토 할 내용이 더 있습니다.

토스트 메시지의 경우 Google 개발자 안내서는 애플리케이션 컨텍스트를 사용하고이를 명시 적으로 사용합니다. 토스트 알림

개발자 안내서의 대화 상자 섹션에서 AlertDialog.Builder가 응용 프로그램 컨텍스트를 사용하고 진행률 막대가 활동 컨텍스트를 사용한다는 것을 알 수 있습니다. 이것은 구글에 의해 설명되지 않습니다. 대화 상자

방향 변경과 같은 구성 변경을 처리하고보기와 같은 컨텍스트가 필요한 객체를 유지하려는 경우 응용 프로그램 컨텍스트를 사용하는 것이 좋습니다. 여기를 보면 : 런타임 변경 사항 활동 컨텍스트 사용에 대한주의가 있으며 이는 누출을 일으킬 수 있습니다. 이것은 유지되어야 할 뷰가있는 응용 프로그램 컨텍스트에서 피할 수 있습니다 (적어도 내 이해입니다). 내가 쓰고있는 응용 프로그램에서는 방향 변경에 대한 일부보기와 다른 것들을 유지하려고 노력하고 있기 때문에 응용 프로그램 컨텍스트를 사용하려고하지만 여전히 방향 변경에서 활동을 파괴하고 다시 만들고 싶습니다. 따라서 메모리 누수가 발생하지 않도록 앱 컨텍스트를 사용해야합니다 ( 메모리 누수 방지 참조).). 나에게 활동 컨텍스트 대신 응용 프로그램 컨텍스트를 사용해야하는 충분한 이유가 많이 있으며, 나에게 당신이 활동 컨텍스트보다 더 자주 사용하는 것처럼 보입니다. 그것은 내가 겪은 많은 안드로이드 서적이며 내가 본 구글 사례의 대부분입니다.

Google 문서는 실제로 대부분의 경우 응용 프로그램 컨텍스트를 사용하는 것이 완벽하게 보이는 것처럼 보이고 실제로는 예제 (적어도 내가 본 예제)에서 활동 컨텍스트를 사용하는 것보다 더 자주 나타납니다. 애플리케이션 컨텍스트를 사용하는 것이 실제로 문제가되는 경우 Google은이를 더욱 강조해야합니다. 그들은 그것을 명확하게해야하고, 그들의 예 중 일부를 다시해야합니다. 권위 (Google)가 실제로 응용 프로그램 컨텍스트를 사용하는 것이 문제가 아닌 것처럼 보이기 때문에 경험이 부족한 개발자에게 전적으로 책임을지지 않습니다.


5
완전히 동의 해. CommonsWare의 대답은 나에게 약간의 놀라움으로 왔습니다. Google 문서에서 getApplicationContext를 사용하는 것이 너무 위험 할 수 있다고 제안했기 때문에이 질문을 발견하게되어 기쁩니다.
Steve Schwarcz

38

나는 같은 상황의 다른 유형을 사용하는 경우에 대한 지침으로이 테이블을 사용하는 응용 프로그램 컨텍스트 (즉, getApplicationContext()와) 활동 상황 , 또한 브로드 캐스트 리시버 컨텍스트 :

여기에 이미지 설명을 입력하십시오

자세한 내용은 여기의 모든 저자가 원저자에게 가십시오 .


11

어떤 컨텍스트를 사용해야합니까?

컨텍스트에는 두 가지 유형이 있습니다.

  1. 응용 프로그램 컨텍스트 는 응용 프로그램과 연결되며 응용 프로그램 수명 동안 항상 동일하지만 변경되지는 않습니다. 따라서 토스트를 사용하는 경우 응용 프로그램의 어느 곳에서나 토스트가 표시 될 수 있고 특정 창에 첨부되지 않기 때문에 응용 프로그램 컨텍스트 또는 활동 컨텍스트 (둘 다)를 사용할 수 있습니다. 그러나 많은 예외가 있지만 한 가지 예외는 활동 컨텍스트를 사용하거나 전달해야 할 때입니다.

  2. 활동 컨텍스트 는 활동과 연관되어 있으며 활동이 파괴되면 소멸 될 수 있습니다. 단일 애플리케이션에 여러 활동이있을 수 있습니다. 때로는 활동 컨텍스트 핸들이 절대적으로 필요합니다. 예를 들어, 새 활동을 시작하는 경우 새 실행 활동이 활동 스택 측면에서 현재 활동에 연결되도록 의도에서 활동 컨텍스트를 사용해야합니다. 그러나 응용 프로그램의 컨텍스트를 사용하여 새 활동을 시작할 수도 있지만 Intent.FLAG_ACTIVITY_NEW_TASK새 작업으로 처리하기 위해 플래그를 설정해야합니다 .

몇 가지 경우를 고려해 봅시다.

  • MainActivity.this 은 Activity 클래스를 확장하는 MainActivity 컨텍스트를 참조하지만 기본 클래스 (activity)도 Context 클래스를 확장하므로 활동 컨텍스트를 제공하는 데 사용할 수 있습니다.

  • getBaseContext() 활동 컨텍스트를 제공합니다.

  • getApplication() 응용 프로그램 컨텍스트를 제공합니다.

  • getApplicationContext() 응용 프로그램 컨텍스트도 제공합니다.

자세한 내용은이 링크 를 확인 하십시오 .


앱에 AlertDialog를 표시 해야하는 경우는 어떻습니까? 예를 들어 결과를 보여주는 비동기 프로세스. 예를 들면 : 사용자가 다운로드를 클릭하면에 대한 다운로드 요청이 발생 downloadmanager하고 완료된 신호가 수신되면 "이 다운로드로 무엇을 하시겠습니까?"라는 대화 상자가 표시됩니다. 내 (해킹) 솔루션은 가장 최근에 저장 ActivityA의 static Application클래스와 현재를 요청 Activity다운로드가 완료되면. 그러나 이것이 올바른 구현인지 의심합니다. TL; DR 앱 어디서나 AlertDialog를 표시하는 방법은 무엇입니까?
CybeX

@KGCybeX 다운로드가 완료 될 때 앱의 아무 곳에 나 표시하려면 다운로드 서비스가 브로드 캐스트하고 메시지를 수신 할 때 원하는 작업을 수행하거나 첨부 할 특정 메시지를 수신하는 활동에 브로드 캐스트 수신기를 수동으로 등록해야합니다. 해당 서비스에 대한 귀하의 활동.
ExiRouS

6

지원하는 모든 작업에 응용 프로그램 컨텍스트를 사용하지 않는 이유가 궁금합니다. 결국 메모리 누수 가능성과 getContext () 또는 getActivity ()에 대한 null 검사 누락 (삽입 된 애플리케이션 컨텍스트를 사용하거나 Application의 정적 메소드를 통해 획득 한 경우)이 줄어 듭니다. 필요한 경우에만 응용 프로그램 컨텍스트를 사용하기 위해 Hackborn 의 진술과 같은 진술 은 이유를 설명하지 않고 설득력있는 것처럼 보이지 않습니다. 그러나 나는 왜 욕설을 발견 한 것 같습니다.

이 규칙을 따르지 않는 일부 Android 버전 / 기기 조합에 문제가 있음을 발견했습니다. 예를 들어, Context가 전달 된 BroadcastReceiver가 있고 해당 Context를 Application Context로 변환 한 다음 Application Context에서 registerReceiver ()를 호출하려고 시도하면이 인스턴스가 제대로 작동하는 인스턴스가 많지만 인스턴스가 많이있는 경우도 있습니다. ReceiverCallNotAllowedException으로 인한 충돌 이러한 충돌은 API 15에서 22까지 다양한 Android 버전에서 발생합니다. https://possiblemobile.com/2013/06/context/#comment-2443283153

아래 표의 애플리케이션 컨텍스트에서 지원하는 것으로 설명 된 모든 작업이 모든 Android 기기에서 작동한다고 보장 할 수는 없습니다! 여기에 이미지 설명을 입력하십시오


4

액티비티 컨텍스트와 애플리케이션 컨텍스트를 함께 사용해야하는 경우의 두 가지 좋은 예는 애플리케이션 컨텍스트를 사용하여 토스트 메시지 또는 내장 된 대화 상자 메시지를 표시 할 때 예외가 발생합니다.

ProgressDialog.show(this, ....);

또는

Toast t = Toast.makeText(this,....);

이 두 가지 모두 애플리케이션 컨텍스트에 제공되지 않은 활동 컨텍스트의 정보가 필요합니다.


5
흠 .. 어떤 Android OS 버전을 테스트 했습니까? 4.4.4에서 테스트했으며 잘 작동합니다. 또한 @Andi Jay가 언급했듯이 공식 Android 개발자 문서는 샘플 코드에서 애플리케이션 컨텍스트를 사용했습니다. developer.android.com/guide/topics/ui/notifiers/…
김준호

1
@Chinese 이름, 예, 작동 할 수도 있지만 언젠가는 해당 앱의 작동이 중단 될 수도 있습니다.
Ojonugwa Jude Ochalifu

1
Toast에서 Activity 컨텍스트를 사용하면 메모리가 누출됩니다!
Jemshit Iskenderov

3

응용 프로그램 컨텍스트 라이브 전까지 응용 프로그램이 살아 만이 활동 수명주기하지만, 문맥에 의존하지 킵 개체 수명이 긴 . 임시로 사용되는 객체 인 경우 해당 시간에 애플리케이션 컨텍스트활동 컨텍스트 가 사용되며 애플리케이션 컨텍스트에 완전히 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.