질문 : Android에서 전역 변수를 선언하는 방법은 무엇입니까?
로그인이 필요한 응용 프로그램을 만들고 있습니다. 메인 및 로그인 활동을 만들었습니다.
기본 활동 onCreate
메서드에서 다음 조건을 추가했습니다.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
loadSettings();
if(strSessionString == null)
{
login();
}
...
}
로그인 양식이 종료 될 때 실행되는 onActivityResult
@Override
public void onActivityResult(int requestCode,
int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case(SHOW_SUBACTICITY_LOGIN):
{
if(resultCode == Activity.RESULT_OK)
{
strSessionString = data.getStringExtra(Login.SESSIONSTRING);
connectionAvailable = true;
strUsername = data.getStringExtra(Login.USERNAME);
}
}
}
문제는 로그인 양식이 때때로 두 번 나타나고 ( login()
메서드가 두 번 호출 됨) 전화 키보드가 슬라이드하면 로그인 양식이 다시 나타나고 문제는 변수 strSessionString
이라고 생각합니다.
사용자가 이미 성공적으로 인증 한 후 로그인 양식이 나타나지 않도록 전역 변수를 설정하는 방법을 아는 사람이 있습니까?
답변
이 답변은 Android가 비교적 새롭고 Android 개발에서 잘 확립되지 않은 영역이 많았던 '09 년에 작성했습니다. 이 게시물의 하단에 긴 부록을 추가하여 일부 비판을 다루고 Application을 서브 클래 싱하는 대신 싱글 톤 사용에 대한 철학적 불일치를 자세히 설명했습니다. 자신의 책임하에 읽으십시오.
원래 답변 :
보다 일반적인 문제는 여러 활동과 애플리케이션의 모든 부분에서 상태를 저장하는 방법입니다. 정적 변수 (예 : 싱글 톤)는이를 달성하는 일반적인 Java 방법입니다. 그러나 Android에서 더 우아한 방법은 상태를 애플리케이션 컨텍스트와 연결하는 것입니다.
아시다시피 각 활동은 가장 넓은 의미의 실행 환경에 대한 정보 인 컨텍스트이기도합니다. 애플리케이션에도 컨텍스트가 있으며 Android는 애플리케이션 전체에서 단일 인스턴스로 존재 함을 보장합니다.
이를 수행하는 방법은 android.app.Application 의 자체 하위 클래스를 만든 다음 매니페스트의 애플리케이션 태그에 해당 클래스를 지정하는 것입니다. 이제 Android는 자동으로 해당 클래스의 인스턴스를 생성하고 전체 애플리케이션에서 사용할 수 있도록합니다. Context.getApplicationContext()
메소드를 사용하여 context
에서 액세스 할 수 있습니다 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();
...
}
}
여기서는 더 우아한 솔루션으로 싱글 톤을 사용하는 것보다 Application 서브 클래 싱을 선호하지만, 실제로 필요한 경우 개발자는 상태를 Application 서브 클래스와 연관시키는 성능 및 멀티 스레딩 의미를 전혀 생각하지 않는 것보다 싱글 톤을 사용하는 것이 좋습니다.
참고 1 : 또한 anticafe가 주석을 달았 듯이 애플리케이션 재정의를 애플리케이션에 올바르게 연결하려면 매니페스트 파일에 태그가 필요합니다. 다시 한 번 더 자세한 정보는 Android 문서를 참조하세요. 예 :
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
참고 2 : user608578은 기본 개체 수명주기를 관리하는 방법을 아래에서 묻습니다. 나는 안드로이드에서 네이티브 코드를 사용하는 데 조금이라도 빠르지 않으며 그것이 내 솔루션과 어떻게 상호 작용하는지 대답 할 자격이 없습니다. 누군가 이것에 대한 답을 가지고 있다면, 나는 그들을 기꺼이 인정하고 최대한의 가시성을 위해이 게시물에 정보를 넣을 것입니다.
추가:
일부 사람들이 지적했듯이 이것은 지속적인 상태에 대한 해결책 이 아니며 원래 답변에서 더 강조 했어야 할 것입니다. 즉, 이것은 사용자 또는 응용 프로그램 수명 동안 유지되는 기타 정보를 저장하기위한 솔루션이 아닙니다. 따라서 디스크에 유지되어야하는 모든 항목이 Application 하위 클래스를 통해 저장되어서는 안되므로 언제든지 종료되는 응용 프로그램 등과 관련된 아래의 대부분의 비판을 고려합니다. 이는 쉽게 다시 만들 수있는 일시적인 응용 프로그램 상태 (예 : 사용자가 로그인했는지 여부) 및 본질적으로 단일 인스턴스 (예 : 응용 프로그램 네트워크 관리자) (단일 항목이 아님) 인 구성 요소를 저장하기위한 솔루션입니다.
Dayerman은 Reto Meier 및 Dianne Hackborn과 의 흥미로운 대화를 지적 할만큼 친절했습니다. Application 하위 클래스의 사용은 Singleton 패턴을 선호하는 것이 권장되지 않습니다. Somatik은 또한 초기에 이러한 성격을 지적했지만 당시에는 보지 못했습니다. Android 플랫폼을 유지하는 Reto와 Dianne의 역할 때문에 나는 선의로 그들의 조언을 무시할 것을 권장 할 수 없습니다. 그들이 말하는 것은 간다. Application 하위 클래스보다 Singleton을 선호하는 것과 관련하여 표현 된 의견에 동의하지 않습니다. 내 의견 불일치에서 Singleton 디자인 패턴에 대한 StackExchange 설명 에서 가장 잘 설명 된 개념을 사용하여이 답변에서 용어를 정의 할 필요가 없습니다. 계속하기 전에 링크를 훑어 보는 것이 좋습니다. 포인트 별 :
Dianne은 "Application에서 서브 클래스 할 이유가 없습니다. 싱글 톤을 만드는 것과 다르지 않습니다 ..."이 첫 번째 주장은 올바르지 않습니다. 여기에는 두 가지 주요 이유가 있습니다. 1) Application 클래스는 응용 프로그램 개발자에게 더 나은 수명 보장을 제공합니다. 응용 프로그램의 수명이 보장됩니다. 싱글 톤은 애플리케이션의 수명과 명시 적으로 연결되지 않습니다 (효과적 임에도 불구하고). 이것은 일반 애플리케이션 개발자에게는 문제가되지 않을 수 있지만 이것이 Android API가 제공해야하는 계약 유형과 정확히 일치하며 관련 수명을 최소화함으로써 Android 시스템에 훨씬 더 많은 유연성을 제공한다고 주장합니다. 데이터. 2) Application 클래스는 상태에 대한 단일 인스턴스 홀더를 응용 프로그램 개발자에게 제공하는데, 이는 상태의 Singleton 홀더와는 매우 다릅니다. 차이점 목록은 위의 싱글 톤 설명 링크를 참조하십시오.
Dianne은 계속해서 "... 당신의 Application 객체가 독립적 인 애플리케이션 로직이되어야하는 것들이 이렇게 엉망진창이되는 것을 발견함에 따라 미래에 후회할 것 같습니다." 이것은 확실히 틀린 것은 아니지만 이것은 응용 프로그램 하위 클래스보다 싱글 톤을 선택하는 이유가 아닙니다. Diane의 주장 중 어느 것도 Singleton을 사용하는 것이 Application 하위 클래스보다 낫다는 이유를 제공하지 않습니다. 그녀가 설정하려는 모든 시도는 Singleton을 사용하는 것이 내가 거짓이라고 생각하는 Application 하위 클래스보다 나쁘지 않다는 것입니다.
그녀는 계속해서 "그리고 이것은 이러한 것들을 어떻게 관리해야하는지, 즉 주문형으로 초기화하는 방법으로 더욱 자연스럽게 이어집니다." 이는 Application 서브 클래스를 사용하여 요청시 초기화 할 수없는 이유가 없다는 사실을 무시합니다. 다시 한 번 차이가 없습니다.
Dianne은 "프레임 워크 자체에는로드 된 리소스의 캐시, 객체 풀 등과 같이 앱에 대해 유지 관리하는 모든 작은 공유 데이터에 대해 수많은 싱글 톤이 있습니다. 훌륭하게 작동합니다." 나는 Singletons를 사용하는 것이 잘 작동하지 않거나 합법적 인 대안이 아니라고 주장하는 것이 아닙니다. 저는 Singletons가 Application 하위 클래스를 사용하는 것만 큼 Android 시스템과 강력한 계약을 제공하지 않으며, 또한 Singletons를 사용하는 것은 일반적으로 쉽게 수정할 수없는 유연하지 않은 디자인을 나타내며 앞으로 많은 문제를 야기한다고 주장합니다. Android API가 개발자 애플리케이션에 제공하는 강력한 계약 인 IMHO는 Android 프로그래밍의 가장 매력적이고 즐거운 측면 중 하나이며, Android 플랫폼을 오늘날의 성공으로 이끄는 초기 개발자 채택으로 이어졌습니다. Singletons 사용을 제안하는 것은 강력한 API 계약에서 묵시적으로 멀어지고 제 생각에는 Android 프레임 워크를 약화시킵니다.
Dianne은 또한 Application 서브 클래스 사용에 대한 추가적인 단점을 언급하면서 아래에서 언급했습니다. 그들은 성능이 떨어지는 코드를 작성하는 것을 장려하거나 더 쉽게 만들 수 있습니다. 이것은 매우 사실이며 여기에서 perf를 고려하고 Application 하위 클래스를 사용하는 경우 올바른 접근 방식을 취하는 중요성을 강조하기 위해이 답변을 편집했습니다. Dianne이 말했듯이, 프로세스가 백그라운드 브로드 캐스트 용으로 만로드 되더라도 프로세스가로드 될 때마다 (애플리케이션이 여러 프로세스에서 실행되는 경우 한 번에 여러 번) Application 클래스가 인스턴스화된다는 점을 기억하는 것이 중요합니다. 행사. 따라서 응용 프로그램의 공유 구성 요소에 대한 포인터의 저장소로 응용 프로그램 클래스를 처리를 수행하는 장소로 사용하는 것이 더 중요합니다!
이전 StackExchange 링크에서 도난당한 Singletons의 단점 목록은 다음과 같습니다.
- 추상 또는 인터페이스 클래스를 사용할 수 없습니다.
- 하위 클래스에 대한 불능;
- 애플리케이션 전반에 걸친 높은 결합 (수정하기 어려움)
- 테스트하기 어려움 (단위 테스트에서 가짜 / 모의 할 수 없음)
- 변경 가능한 상태의 경우 병렬화하기 어려움 (광범위한 잠금이 필요함)
내 자신을 추가하십시오.
- Android (또는 대부분의 기타) 개발에 적합하지 않은 불명확하고 관리 할 수없는 평생 계약
출처 : https://stackoverflow.com/questions/708012/how-to-declare-global-variables-in-android
'프로그래밍 언어 > Android' 카테고리의 다른 글
새 Android 조각을 인스턴스화하는 모범 사례 (0) | 2021.11.02 |
---|---|
Android Studio에 라이브러리 프로젝트를 추가하는 방법 (0) | 2021.11.02 |
Android 레이아웃에서 텍스트에 밑줄을 긋는 방법 (0) | 2021.11.01 |
Android에서 활동 시작시 EditText가 포커스를 얻지 못하도록 하는 방법 (0) | 2021.10.27 |
Android에서 'Context'를 얻는 방법 (0) | 2021.10.26 |