나는 안드로이드가 상대적으로 새로운 것이었던 09 년에이 답변을 썼고, 안드로이드 개발에 잘 확립되지 않은 영역이 많았다. 이 게시물의 맨 아래에 긴 비평을 추가하여 비판을 언급하고 Application을 서브 클래 싱하는 것이 아니라 Singleton을 사용하는 것에 대한 철학적 불일치를 자세히 설명했습니다. 자신의 책임하에 읽으십시오.
원래 답변 :
가장 일반적인 문제는 여러 활동과 애플리케이션의 모든 부분에서 상태를 저장하는 방법입니다. 정적 변수 (예 : 싱글 톤)는이를 달성하는 일반적인 Java 방법입니다. 그러나 Android에서보다 우아한 방법은 상태를 응용 프로그램 컨텍스트와 연결하는 것입니다.
아시다시피, 각 활동은 컨텍스트입니다. 컨텍스트는 가장 넓은 의미에서 실행 환경에 대한 정보입니다. 애플리케이션에는 컨텍스트가 있으며 Android는 애플리케이션 전체에서 단일 인스턴스로 존재 함을 보장합니다.
이를 수행하는 방법은 android.app.Application 의 자체 서브 클래스를 작성한 후 매니페스트의 애플리케이션 태그에서 해당 클래스를 지정하는 것입니다. 이제 Android는 해당 클래스의 인스턴스를 자동으로 생성하여 전체 애플리케이션에서 사용할 수있게합니다. 메소드를 context
사용하여 액세스 할 수 있습니다 Context.getApplicationContext()
( 똑같은 효과를 갖는 Activity
메소드도 제공 getApplication()
). 다음은주의해야 할 매우 간단한 예입니다.
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
이것은 본질적으로 정적 변수 또는 싱글 톤을 사용하는 것과 동일한 효과가 있지만 기존 Android 프레임 워크에 상당히 잘 통합됩니다. 이것은 여러 프로세스에서 작동하지 않습니다 (앱이 여러 프로세스를 가진 드문 앱 중 하나 여야 함).
위의 예에서 참고할 사항 대신 다음과 같은 작업을 수행했다고 가정합니다.
class MyApp extends Application {
private String myState = /* complicated and slow initialization */;
public String getState(){
return myState;
}
}
이제 응용 프로그램이 인스턴스화 될 때마다이 느린 초기화 (예 : 디스크 치기, 네트워크 치기, 차단 등)가 수행됩니다! 당신은 생각할지도 모릅니다. 이것은 프로세스에 대해 한 번만 발생합니다. 어쨌든 비용을 지불해야합니다. 예를 들어 Dianne Hackborn이 아래에 언급 한 것처럼 백그라운드 브로드 캐스트 이벤트를 처리하기 위해 프로세스를 인스턴스화 할 수 있습니다. 방송 처리가이 상태를 필요로하지 않는다면, 당신은 단지 일련의 복잡하고 느린 작업을 전혀하지 않았을 것입니다. 게으른 인스턴스화는 여기서 게임의 이름입니다. 다음은 응용 프로그램을 사용하는 약간 더 복잡한 방법으로 가장 간단한 용도 이외의 용도에 더 적합합니다.
class MyApp extends Application {
private MyStateManager myStateManager = new MyStateManager();
public MyStateManager getStateManager(){
return myStateManager ;
}
}
class MyStateManager {
MyStateManager() {
/* this should be fast */
}
String getState() {
/* if necessary, perform blocking calls here */
/* make sure to deal with any multithreading/synchronicity issues */
...
return state;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
String state = stateManager.getState();
...
}
}
여기서는 응용 프로그램 하위 클래스를보다 우아한 솔루션으로 사용하는 것보다 단일 응용 프로그램을 선호하지만 개발자는 응용 프로그램 하위 클래스와 상태를 연결하는 성능 및 멀티 스레딩 영향을 전혀 생각하지 않고 단일 톤을 사용하는 것이 좋습니다.
참고 1 : 안티 카페 (Anticafe)에서 언급 한 것처럼 애플리케이션 재정의를 애플리케이션에 올바르게 연결하려면 매니페스트 파일에 태그가 필요합니다. 자세한 내용은 Android 문서를 참조하십시오. 예를 들면 :
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
참고 2 : user608578은 아래에서 기본 개체 수명주기 관리에 대한 작동 방식을 묻습니다. 나는 안드로이드에서 네이티브 코드를 사용하는 데 약간의 시간이 걸리지 않으며 솔루션과의 상호 작용 방식에 대답 할 자격이 없습니다. 누군가가 이것에 대한 답변을 가지고 있다면, 나는 그것들을 신용하고 최대한의 가시성을 위해이 게시물에 정보를 넣을 것입니다.
추가:
일부 사람들이 지적했듯이, 이것은 지속적인 상태에 대한 해결책 이 아니며 원래의 대답에서 더 강조했을 것입니다. 즉, 이것은 응용 프로그램 수명 기간 동안 유지되어야하는 사용자 또는 기타 정보를 저장하기위한 솔루션이 아닙니다. 따라서 디스크에 유지해야 할 것은 응용 프로그램 하위 클래스를 통해 저장해서는 안되기 때문에 언제든지 종료되는 응용 프로그램 등과 관련하여 아래의 대부분의 비판을 고려합니다. 이는 (예를 들어 사용자가 로그인했는지 여부에 관계없이) 일시적이고 쉽게 재현 가능한 응용 프로그램 상태 및 단일 인스턴스 (예 : 응용 프로그램 네트워크 관리자) ( 싱글 톤이 아님 ) 인 구성 요소를 저장하기위한 솔루션입니다 .
Dayerman은 Reton Meier 및 Dianne Hackborn과 의 흥미로운 대화 를 지적하기에 충분히 친절 했습니다. 여기서 응용 프로그램 서브 클래스 사용은 싱글 톤 패턴을 선호하지 않습니다. 소마 틱은 또한 당시에는 보지 못했지만이 특성을 더 일찍 지적했다. 안드로이드 플랫폼을 유지하는 데있어 Reto와 Dianne의 역할 때문에, 나는 그들의 조언을 무시할 것을 선의로 권고 할 수 없습니다. 그들이 말하는 것은 간다. Singleton over Application 서브 클래스를 선호하는 것과 관련하여 표현 된 의견에 동의하지 않습니다. 동의하지 않을 때는 Single Stack 디자인 패턴에 대한이 StackExchange 설명 에서 가장 잘 설명 된 개념을 사용할 것 입니다.이 답변에서 용어를 정의 할 필요가 없습니다. 계속하기 전에 링크를 감추는 것이 좋습니다. 포인트 별 :
Dianne은 "애플리케이션에서 서브 클래스를 만들 이유가 없습니다. 싱글 톤을 만드는 것과 다르지 않습니다 ..."이 첫 번째 주장은 잘못되었습니다. 여기에는 두 가지 주요 이유가 있습니다. 1) 응용 프로그램 클래스는 응용 프로그램 개발자에게 더 나은 평생 보증을 제공합니다. 응용 프로그램의 수명을 보장합니다. 싱글 톤은 응용 프로그램의 수명과 명시 적으로 연결되어 있지 않습니다 (실제로 효과적 임). 이것은 일반적인 응용 프로그램 개발자에게는 문제가 아닐 수 있지만 이것이 Android API가 제공 해야하는 계약 유형이며, 관련 수명을 최소화하여 Android 시스템에 훨씬 더 많은 유연성을 제공한다고 주장합니다. 데이터. 2) Application 클래스는 애플리케이션 개발자에게 상태에 대한 단일 인스턴스 홀더를 제공합니다. 이것은 싱글턴 상태 보유자와는 매우 다릅니다. 차이점 목록은 위의 싱글 톤 설명 링크를 참조하십시오.
Dianne은 "... 응용 프로그램 객체가 독립적 인 응용 프로그램 로직이 무엇인지에 대한 큰 혼란을 겪고 있다는 것을 알게되면서 미래에 당신이 후회하게 될 것"이라고 계속 말했다. 이것은 확실히 부정확하지는 않지만 Singleton over Application 서브 클래스를 선택하는 이유는 아닙니다. Diane의 주장 중 어느 것도 Singleton을 사용하는 것이 Application 하위 클래스보다 낫다는 이유를 제공하지 않으며, Singleton을 사용하는 것이 Application 하위 클래스보다 나쁘지 않다는 것입니다.
그녀는 계속해서 "그리고 이것은 자연스럽게 이러한 것들을 어떻게 관리해야하는지에 따라 더욱 필요할 때마다 초기화합니다." 이것은 Application 서브 클래스를 사용하여 요청시 초기화 할 수없는 이유가 없다는 사실을 무시합니다. 또 차이는 없습니다.
Dianne은 "프레임 워크 자체에는로드 된 리소스의 캐시, 객체 풀 등과 같이 앱을 위해 유지 관리하는 모든 작은 공유 데이터에 대해 톤과 톤의 싱글 톤이 있습니다. 나는 Singleton을 사용하는 것이 잘 작동하지 않거나 합법적 인 대안이 아니라고 주장하지 않습니다. Singletons는 Application 하위 클래스를 사용하는 것만 큼 Android 시스템과 강력한 계약을 제공하지 않으며 Singletons를 사용하면 일반적으로 쉽게 수정할 수없는 융통성없는 디자인을 가리키며 많은 문제가 발생한다고 주장합니다. 안드로이드 API가 개발자 애플리케이션에 제공하는 강력한 계약 인 IMHO는 안드로이드 프로그래밍의 가장 매력적이고 즐거운 측면 중 하나이며, 초기 개발자 채택으로 이어져 오늘날 Android 플랫폼을 성공으로 이끌었습니다.
Dianne은 응용 프로그램 서브 클래스를 사용하는 것에 대한 추가적인 단점을 언급하면서 아래에 주석을 달았으므로 성능이 떨어지는 코드를 작성하거나 쉽게 작성할 수 있습니다. 이것은 매우 사실이며 여기에서 성능을 고려하고 응용 프로그램 하위 클래스를 사용하는 경우 올바른 접근 방식을 취하는 것이 중요하다는 것을 강조하기 위해이 답변을 편집했습니다. Dianne이 말했듯이 프로세스가 백그라운드 브로드 캐스트에만로드되는 경우에도 프로세스가로드 될 때마다 (클래스가 여러 프로세스에서 실행될 경우 한 번에 여러 번 발생할 수 있음) Application 클래스가 인스턴스화된다는 점을 기억해야합니다. 행사. 따라서 응용 프로그램 클래스를 처리하는 장소가 아니라 응용 프로그램의 공유 구성 요소에 대한 포인터의 저장소로 사용하는 것이 중요합니다!
이전 StackExchange 링크에서 도난당한 다음 싱글 톤 단점 목록을 남겨 둡니다.
- 추상 또는 인터페이스 클래스를 사용할 수 없음
- 서브 클래스 불가능
- 응용 분야에서 높은 커플 링 (수정하기 어려움);
- 테스트하기 어려움 (단위 테스트에서 위조 / 조롱 할 수 없음);
- 변경 가능한 상태의 경우 병렬화하기 어려움 (광범위한 잠금이 필요함);
내 자신을 추가하십시오.
- 안드로이드 (또는 대부분의 다른) 개발에 적합하지 않은 불분명하고 관리 불가능한 평생 계약;