source

안드로이드에서 글로벌 변수를 선언하는 방법은 무엇입니까?

ittop 2023. 6. 1. 22:56
반응형

안드로이드에서 글로벌 변수를 선언하는 방법은 무엇입니까?

로그인이 필요한 애플리케이션을 만들고 있습니다.메인과 로그인 활동을 만들었습니다.

onCreate 조건을 추가했습니다. method I 다 조 추 가 습 니 했 다 을 건 은 음 니 다 습 ▁method 했 : ▁the 추 가

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.

사용자가 이미 인증에 성공한 후 로그인 양식이 나타나지 않도록 변수를 글로벌로 설정하는 방법을 아는 사람이 있습니까?

안드로이드가 비교적 새로워지고, 안드로이드 개발에서 잘 정립되지 않은 분야가 많았던 지난 09년에 이 답변을 작성했습니다.저는 이 게시물 하단에 긴 부록을 추가하여 일부 비판을 다루고 애플리케이션을 하위 분류하기보다는 싱글턴을 사용하는 것에 대해 제가 가지고 있는 철학적 불일치를 자세히 설명했습니다.당신의 책임 하에 그것을 읽으세요.

원답:

여러 활동 및 응용프로그램의 모든 부분에서 상태를 저장하는 방법이 더 일반적인 문제입니다.정적 변수(예: 싱글톤)는 이를 달성하는 일반적인 Java 방법입니다.하지만 Android에서 더 우아한 방법은 상태를 애플리케이션 컨텍스트와 연결하는 것입니다.

아시다시피, 각 활동은 가장 광범위한 의미에서 실행 환경에 대한 정보인 컨텍스트이기도 합니다.응용프로그램에도 컨텍스트가 있으며 Android는 응용프로그램 전체에 걸쳐 단일 인스턴스로 존재할 것을 보장합니다.

이를 위한 방법은 안드로이드.app의 하위 클래스를 만드는 것입니다.응용 프로그램을 선택한 다음 매니페스트의 응용 프로그램 태그에 해당 클래스를 지정합니다.이제 Android는 해당 클래스의 인스턴스를 자동으로 생성하여 전체 응용 프로그램에서 사용할 수 있도록 합니다.아무 곳에서나 액세스할 수 있습니다.context 사용Context.getApplicationContext()method)Activity 메소드 " 메드제공다니합를또소한▁a▁method다"도 제공합니다.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();
    ...
  }
}

이는 정적 변수나 싱글톤을 사용하는 것과 본질적으로 동일한 효과를 가지지만 기존 안드로이드 프레임워크에 상당히 잘 통합됩니다.이는 프로세스 간에 작동하지 않습니다(앱이 여러 프로세스를 가진 드문 앱인 경우).

위의 예에서 주목해야 할 점이 있습니다. 대신 다음과 같은 작업을 수행했다고 가정합니다.

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: 또한 안티카페에서 언급한 바와 같이 응용프로그램 오버라이드를 응용프로그램에 올바르게 연결하려면 매니페스트 파일에 태그가 필요합니다.다시 한 번 자세한 내용은 Android 문서를 참조하십시오.예:

<application
     android:name="my.application.MyApp" 
     android:icon="..."
     android:label="...">
</application>

참고 2: 사용자 608578은 기본 개체 수명 주기를 관리할 때 이 기능이 어떻게 작동하는지 아래에 질문합니다.Android에서 네이티브 코드를 사용하는 것에 대해 조금도 속도를 낼 수 없으며, 그것이 내 솔루션과 어떻게 상호 작용하는지에 대해 대답할 자격이 없습니다.만약 누군가가 이것에 대한 답을 가지고 있다면, 나는 기꺼이 그들에게 공을 돌리고 최대한의 가시성을 위해 이 게시물에 정보를 넣을 것입니다.

부록:

몇몇 사람들이 지적했듯이, 이것은 지속적인 상태에 대한 해결책이 아니며, 아마도 제가 원래 답변에서 더 강조했어야 할 것입니다.즉, 사용자 또는 애플리케이션 수명에 걸쳐 지속되는 기타 정보를 저장하기 위한 솔루션이 아닙니다.따라서 언제든지 애플리케이션이 삭제되는 등과 관련된 아래의 대부분의 비판은 디스크에 지속되어야 하는 모든 것이 애플리케이션 하위 클래스를 통해 저장되어서는 안 되기 때문입니다.이 솔루션은 임시적이고 쉽게 다시 생성할 수 있는 애플리케이션 상태(예: 사용자 로그인 여부)와 단일 인스턴스(예: 애플리케이션 네트워크 관리자)인 구성 요소(싱글턴이 아님!)를 저장하기 위한 솔루션입니다.

데이먼은 레토 마이어와 다이앤 해크본과 함께 싱글턴 패턴을 선호하는 애플리케이션 하위 클래스의 사용이 권장되지 않는 흥미로운 대화를 지적할 정도로 친절했습니다.소마틱도 그 당시에는 보지 못했지만 앞서 이런 성질의 것을 지적했습니다.안드로이드 플랫폼을 유지하는 데 있어서 레토와 다이앤의 역할 때문에 그들의 조언을 무시하는 것을 진심으로 추천할 수 없습니다.그들이 말하는 것은 갑니다.애플리케이션 하위 클래스보다 싱글턴을 선호하는 것과 관련하여 표명된 의견에 동의하지 않습니다.저는 이 답변에서 용어를 정의할 필요가 없도록 싱글턴 디자인 패턴에 대한 StackExchange 설명에서 가장 잘 설명된 개념을 사용할 것입니다.계속하기 전에 링크를 건너뛰는 것이 좋습니다.포인트 바이 포인트:

Dianne은 다음과 같이 말합니다. "애플리케이션에서 하위 클래스를 지정할 이유가 없습니다.1톤을 만드는 것과 다름이 없습니다." 이 첫 번째 주장은 잘못된 것입니다.그 이유는 크게 두 가지가 있습니다. 1) 애플리케이션 클래스는 애플리케이션 개발자에게 더 나은 수명 보장을 제공합니다. 애플리케이션의 수명이 보장됩니다.싱글톤은 애플리케이션의 수명과 명시적으로 연결되지 않습니다(효과적이긴 하지만).이는 일반적인 애플리케이션 개발자에게는 문제가 되지 않을 수 있지만, 저는 이것이 바로 Android API가 제공해야 하는 계약 유형이며, 관련 데이터의 수명을 최소화함으로써 Android 시스템에도 훨씬 더 많은 유연성을 제공한다고 주장합니다.응용 프로그램 클래스는 응용 프로그램 개발자에게 상태에 대한 단일 인스턴스 홀더를 제공하며, 이는 상태에 대한 Singleton 홀더와는 매우 다릅니다.차이 목록은 위의 Singleton 설명 링크를 참조하십시오.

Dianne은 계속해서 "...애플리케이션 객체가 독립적인 애플리케이션 로직으로 인해 뒤죽박죽이 되어버린 것을 알게 되면 미래에 후회하게 될 것입니다."라고 말합니다.이것은 확실히 잘못된 것은 아니지만, 이것이 애플리케이션 하위 클래스보다 싱글턴을 선택하는 이유는 아닙니다.Diane의 주장 중 어느 것도 싱글턴을 사용하는 것이 애플리케이션 하위 클래스보다 낫다는 이유를 제공하지 않으며, 그녀가 확립하려는 것은 싱글턴을 사용하는 것이 애플리케이션 하위 클래스보다 나쁘지 않다는 것이며, 이는 거짓이라고 생각합니다.

그녀는 계속해서 말합니다. "그리고 이것은 이러한 것들을 관리하는 방법으로 더 자연스럽게 이어집니다. 즉, 온디맨드로 초기화하는 것입니다."이는 애플리케이션 하위 클래스를 사용하여 온디맨드로 초기화할 수 없는 이유가 없다는 사실을 무시합니다.다시 말하지만, 차이는 없습니다.

Dianne은 "프레임워크 자체는 로드된 리소스의 캐시, 개체 풀 등 애플리케이션에 대해 유지 관리하는 모든 작은 공유 데이터에 대해 수많은 싱글톤을 보유하고 있습니다.잘 작동합니다."나는 싱글턴을 사용하는 것이 잘 작동하지 않거나 합법적인 대안이 아니라고 주장하는 것이 아닙니다.저는 싱글턴이 애플리케이션 하위 클래스를 사용하는 것만큼 안드로이드 시스템과 강력한 계약을 제공하지 않으며, 더 나아가 싱글턴을 사용하는 것은 일반적으로 쉽게 수정되지 않는 유연하지 않은 설계를 가리키며 앞으로 많은 문제를 야기할 것이라고 주장합니다.개발자 애플리케이션에 Android API가 제공하는 강력한 계약인 IMHO는 Android를 사용한 프로그래밍의 가장 매력적이고 즐거운 측면 중 하나이며 Android 플랫폼을 오늘날 성공으로 이끈 개발자의 조기 채택을 이끌었습니다.싱글턴을 사용하자는 제안은 암묵적으로 강력한 API 계약에서 벗어나 안드로이드 프레임워크를 약화시키는 것입니다.

Dianne은 애플리케이션 하위 클래스를 사용하는 것에 대한 추가적인 단점을 언급하면서, 성능 코드를 적게 작성하도록 권장하거나 더 쉽게 만들 수 있다고 아래에 언급했습니다.이는 매우 사실이며, 응용프로그램 하위 분류를 사용하는 경우 성능을 고려하고 올바른 접근 방식을 취하는 것이 중요하다는 점을 강조하기 위해 이 답변을 편집했습니다.Dianne의 말처럼 백그라운드 브로드캐스트 이벤트에 대해서만 프로세스가 로드되는 경우에도 프로세스가 로드될 때마다 애플리케이션 클래스가 인스턴스화됩니다(애플리케이션이 여러 프로세스에서 실행되는 경우 한 번에 여러 번 인스턴스화될 수 있습니다!).따라서 응용프로그램 클래스를 처리를 수행하는 장소가 아니라 응용프로그램의 공유 구성요소에 대한 포인터 저장소로 사용하는 것이 더 중요합니다.

이전 StackExchange 링크에서 도난당한 싱글톤의 단점을 다음과 같이 알려드립니다.

  • 추상 클래스 또는 인터페이스 클래스를 사용할 수 없음
  • 하위 분류할 수 없음;
  • 애플리케이션 전반에 걸쳐 높은 결합(수정이 어려운 경우)
  • 테스트하기 어려움(유닛 테스트에서 가짜/모킹할 수 없음);
  • 가변 상태의 경우 병렬 처리가 어렵습니다(광범위한 잠금이 필요함).

그리고 내 것을 추가합니다.

  • Android(또는 대부분의 다른) 개발에 적합하지 않은 불확실하고 관리 불가능한 평생 계약

이 하위 클래스 만들기

public class MyApp extends Application {
  String foo;
}

AndroidManifest.xml에서 Android:name 추가

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

순일이 제안한 애플리케이션 상태 유지 방법은 좋지만 한 가지 단점이 있습니다. OS가 애플리케이션 프로세스 전체를 죽이는 경우가 있습니다.다음은 프로세스라이프사이클에 대한 문서입니다.

예를 들어, 누군가가 당신을 부르고 있기 때문에 당신의 앱은 백그라운드로 이동합니다(전화 앱은 지금 맨 앞에 있습니다).의 다른에서 (위하십시오) 시킬 수 . 를 들어, " " & & & 다 위 에 는 이 확 인 지 될 있 수 는 무 조 이 른 있 엇 이 애 수 다 니 프 습 중 우 경 션 를 서 스 할 세 지 건 로케리플한다포음을함서에크 링 ▁in는▁the▁kill▁your 위 check,이&▁including▁mayation▁process▁someApplication됩니다.결과적으로 국가는 상실됩니다.하고 "" "" "" "" "" "" "" "" "" "" " "" " "" " " "" " " " " " " " " " " " " " " " " " 을 복원합니다.Application 하위 인스턴스인 " 하클스인스턴스나그러래위,"myState는 드는필입니다.null.

정보를 하거나 AFAIK를 등 상태를 입니다. 예를 들어, 애플리케이션 파일에 개인 정보를 사용하거나SharedPrefernces(결국 내부 파일 시스템의 응용프로그램 파일에 개인 파일을 사용합니다.)

메모 하나만..

추가:

android:name=".Globals"

또는 기존의 하위 클래스에 이름을 붙인 것이 무엇이든. <application>tag.는 계속해서 그태를 더 . 다른 태그를 추가하려고 계속 시도했습니다.<application>매니페스트에 태그를 지정하면 예외가 발생합니다.

이러한 글로벌 구조로 네이티브 메모리의 수집을 보장하는 것은 어떻습니까?

에는 활은다이있다니습음동▁an다있▁activ가 있습니다.onPause/onDestroy()메서드는 삭제 시 호출되지만 응용 프로그램 클래스에는 동등한 메서드가 없습니다.응용 프로그램이 중지되거나 작업 스택이 백그라운드에 배치될 때 글로벌 구조(특히 네이티브 메모리에 대한 참조가 포함된 구조)가 적절하게 수집되도록 하려면 어떤 메커니즘이 권장됩니까?

응용 프로그램 태그를 지정하는 방법도 찾을 수 없었지만, 구글링을 많이 한 후 응용 프로그램 스탠자의 기본 아이콘과 레이블 외에 안드로이드: 이름을 사용하는 것이 매니페스트 파일 문서에서 명확해졌습니다.

rodroid:name 응용 프로그램에 대해 구현된 응용 프로그램 하위 클래스의 정규화된 이름입니다.응용 프로그램 프로세스가 시작되면 이 클래스는 응용 프로그램의 구성 요소보다 먼저 인스턴스화됩니다.

하위 클래스는 선택 사항이며 대부분의 응용 프로그램에는 하위 클래스가 필요하지 않습니다.하위 클래스가 없는 경우 Android는 기본 응용 프로그램 클래스의 인스턴스를 사용합니다.

다음과 같이 응용프로그램 이름을 정의하면 됩니다.

<application
  android:name="ApplicationName" android:icon="@drawable/icon">
</application>

위에서 논의한 것처럼 OS는 알림 없이 애플리케이션을 종료할 수 있으므로(onDestroy 이벤트가 없음) 이러한 글로벌 변수를 저장할 방법이 없습니다.

Shared Preferences는 복잡한 구조화 변수(내 경우 사용자가 이미 처리한 ID를 저장하는 정수 배열)를 제외하고 해결책이 될 수 있습니다.공유 기본 설정의 문제는 값이 필요할 때마다 이러한 구조를 저장하고 검색하기 어렵다는 것입니다.

저의 경우 백그라운드 서비스가 있어서 이 변수를 그곳으로 이동할 수 있었고 서비스가 Destroy 이벤트를 실행하고 있기 때문에 쉽게 값을 저장할 수 있었습니다.

일부 변수가 sqlite에 저장되어 있고 앱의 대부분의 작업에서 변수를 사용해야 하는 경우.그러면 애플리케이션이 이를 달성하는 가장 좋은 방법이 될 수 있습니다.응용프로그램이 시작될 때 데이터베이스에서 변수를 쿼리하고 필드에 저장합니다.그런 다음 이러한 변수를 활동에 사용할 수 있습니다.

그러니 올바른 방법을 찾으라, 그러면 최선의 방법은 없습니다.

이러한 상태를 저장하는 정적 필드를 사용할 수 있습니다.또는 리소스 번들에 저장한 후 생성 시 복원합니다(Bundle saved InstanceState).Android 앱 관리 라이프사이클을 완전히 이해했는지 확인하십시오(예: 키보드 방향 변경 시 로그인()이 호출되는 이유).

다른 제품을 사용하지 마십시오.<application>태그가 매니페스트 파일에 있습니다.기존 환경에서 한 번만 변경<application>,이합니다.android:name=".ApplicationName" 디에어,ApplicationName작성하려는 하위 클래스의 이름이 됩니다(글로벌 저장에 사용).

그래서, 마침내 당신의 유일한 것. <application>는 다음과 합니다 :- 니스파태다같합니아다야:-

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:name=".ApplicationName"
        >

Intents, Sqlite 또는 Shared Preferences를 사용할 수 있습니다.문서, 사진 및 비디오와 같은 미디어 저장소의 경우 새 파일을 대신 생성할 수 있습니다.

두 가지 방법을 사용하여 이 작업을 수행할 수 있습니다.

  1. 응용 프로그램 클래스 사용
  2. 공유 환경설정 사용

  3. 응용 프로그램 클래스 사용

예:

class SessionManager extends Application{

  String sessionKey;

  setSessionKey(String key){
    this.sessionKey=key;
  }

  String getSessisonKey(){
    return this.sessionKey;
  }
}

위 클래스를 사용하여 아래와 같이 기본 활동에 로그인을 구현할 수 있습니다.코드는 다음과 같이 표시됩니다.

@override 
public void onCreate (Bundle savedInstanceState){
  // you will this key when first time login is successful.
  SessionManager session= (SessionManager)getApplicationContext();
  String key=getSessisonKey.getKey();
  //Use this key to identify whether session is alive or not.
}

이 방법은 임시 저장에 사용할 수 있습니다.메모리가 부족하기 때문에 운영 체제가 언제 애플리케이션을 종료할지 전혀 알 수 없습니다.응용 프로그램이 백그라운드에 있고 사용자가 실행하기 위해 더 많은 메모리를 요구하는 다른 응용 프로그램을 탐색하는 경우 운영 체제가 백그라운드보다 포그라운드 프로세스에 더 많은 우선 순위를 부여하므로 응용 프로그램이 삭제됩니다.따라서 사용자가 로그아웃하기 전에 응용 프로그램 개체가 null이 됩니다.따라서 위에서 지정한 두 번째 방법을 사용하는 것이 좋습니다.

  1. 공유 환경설정 사용.

    String MYPREF="com.your.application.session"
    
    SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
    
    //Insert key as below:
    
    Editot editor= pref.edit();
    
    editor.putString("key","value");
    
    editor.commit();
    
    //Get key as below.
    
    SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
    
    String key= getResources().getString("key");
    

활동 결과는 이력서 전에 호출됩니다.따라서 로그인 확인을 다시 시작할 때로 이동하면 두 번째 활동이 긍정적인 결과를 반환하면 두 번째 로그인이 차단될 수 있습니다.이력서는 매번 전화를 하기 때문에 한 번도 전화를 받지 않을 걱정이 없습니다.

하위 분류의 접근 방식은 또한 BARACUS 프레임워크에 의해 사용되었습니다.제 관점에서 애플리케이션을 하위 분류하는 것은 Android의 라이프사이클과 함께 작동하기 위한 것입니다. 이것이 모든 애플리케이션 컨테이너가 하는 일입니다.저는 글로벌을 갖는 대신 콩을 이 컨텍스트에 등록하고 컨텍스트에서 관리할 수 있는 모든 클래스에 주입하도록 합니다.주사된 모든 콩 인스턴스는 실제로 1톤입니다.

자세한 내용은 이 예를 참조하십시오.

더 많은 것을 가질 수 있는데 왜 수동 작업을 합니까?

class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}

당신은 확되는클만수있다니습들를장을 확장하는 수 .Application클래스를 지정한 다음 변수를 해당 클래스의 필드로 선언하고 더 나은 방법을 제공합니다.

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

그런 다음 활동에서 해당 변수에 액세스하려면 다음을 사용합니다.

MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();

언급URL : https://stackoverflow.com/questions/708012/how-to-declare-global-variables-in-android

반응형