Android 애플리케이션 클래스를 사용하여 데이터 유지


112

나는 응용 프로그램에 대해 다소 많은 양의 데이터가 필요한 상당히 복잡한 Android 응용 프로그램을 작업하고 있습니다 (총 약 500KB라고 말하고 싶습니다-모바일 장치의 경우이 크기입니까?). 내가 알 수 있듯이, 응용 프로그램의 모든 방향 변경 (보다 정확하게는 활동에서)은 활동의 완전한 파괴 및 재생성을 유발합니다. 내 결과에 따르면 Application 클래스는 동일한 수명주기를 갖지 않습니다 (즉, 모든 의도와 목적을 위해 항상 인스턴스화 됨). 애플리케이션 클래스 내부에 상태 정보를 저장 한 다음 Activity에서 참조하는 것이 합리적입니까? 아니면 일반적으로 모바일 장치의 메모리 제약으로 인해 "허용되는"방법이 아닌가? 이 주제에 대한 조언을 정말 감사합니다. 감사!


8
앱이 백그라운드로 전환되는 경우에도 애플리케이션의 데이터를 삭제할 수 있으므로 항상 복구 할 수 있도록하려는 데이터를 유지하는 솔루션이 아닙니다. 값 비싼 개체를 자주 다시 만들지 않아도되는 방법 일뿐입니다.
Cheryl Simon

2
Mayra; 나는 앱이 "보통"삭제되었다고 생각하지 않는다 (이 스레드의 뒷부분에서 누군가 지적했듯이 "가능"하다). 응용 프로그램을 사용하여 데이터를 저장하고로드하는 "하이브리드"접근 방식을 사용하지만 매니페스트 파일의 활동에 "android : orientation"속성을 사용하여 정상적인 동작을 재정의 할 것입니다. 활동을 해체하고 재건합니다. 물론이 모든 것은 데이터가 지속될 수 있도록 애플리케이션이 파괴되는 "언제"를 결정할 수 있다고 가정합니다.
Dave

답변:


134

나는 500kb가 그렇게 큰 거래가 될 것이라고 생각하지 않습니다.

설명하신 내용은 활동에서 데이터를 잃는 문제를 정확히 어떻게 해결했는지에 대한 것입니다. Application 클래스에서 글로벌 싱글 톤을 생성하고 내가 사용한 활동에서 액세스 할 수있었습니다.

많이 사용될 경우 Global Singleton에서 데이터를 전달할 수 있습니다.

public class YourApplication extends Application 
{     
     public SomeDataClass data = new SomeDataClass();
}

그런 다음 모든 활동에서 다음과 같이 호출하십시오.

YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here.

여기 내 블로그 게시물 "Global Singleton"섹션 에서 논의합니다 .


1
불행히도 문제의 블로그 게시물은 더 이상 해당 주소에서 사용할 수 없습니다.
mikebabcock 2014 년

1
내 사이트에서 물건을 옮기고 있습니다. 문제가 해결 될 때까지 archive.org에서 찾을 수 있습니다 : web.archive.org/web/20130818035631/http://www.bryandenny.com/…
Bryan Denny

1
나는 이것이 오래된 게시물이라는 것을 알고 있지만 이것이 해결할 수있는 문제를 발견했지만이 클래스는 어떻게 든 매니페스트에서 declaired해야합니다. 이런 느낌은 내가 ... 실종 무엇 때문에 내가 클래스를 acsses 수 없습니다
지브 Kesten

1
@ZivKesten 매니페스트 내의 애플리케이션 태그에 name = 속성을 추가하는 것은 어떻습니까?
MikeC 2014

@mgc는 오랜만에 감사합니다. 그래야 결국 해결되었습니다. 또한이 클래스에 대한 캐스트와 함께 getApplicationContext ()를 제공하여 필요한 모든 곳에 해당 클래스의 인스턴스를 만들었습니다
Ziv Kesten

57

Application인스턴스 에 의존하는 사람들 은 잘못되었습니다. 처음 Application에는 전체 앱 프로세스가 존재 하는 한 존재하는 것처럼 보일 수 있지만 이것은 잘못된 가정입니다.

OS는 필요에 따라 프로세스를 종료 할 수 있습니다. 모든 프로세스는 문서에 지정된 5 단계의 "killability"로 나뉩니다 .

예를 들어 사용자가 수신 전화에 응답하여 앱이 백그라운드로 전환되면 RAM 상태에 따라 OS가 프로세스를 종료 (또는 프로세스의 Application인스턴스 파괴 ) 할 수 있습니다. .

더 나은 접근 방식은 데이터를 내부 저장소 파일에 저장 한 다음 활동이 재개 될 때 읽는 것입니다.

최신 정보:

부정적인 피드백을 많이 받았으므로 설명을 추가 할 때입니다. :) 글쎄, 처음에는 상태가 앱에 정말 중요하다는 잘못된 가정을 실제로 사용했습니다. 앱이 때때로 상태가 손실되는 것을 확인하는 경우 그러나 (그냥 다시 읽기 / 다시 다운로드됩니다 일부 이미지 수),의 구성원으로 유지하기 위해 완전히 OK입니다 Application.


14
응용 프로그램이 죽으면 누가 신경 쓰죠? 응용 프로그램이 사라졌습니다. 내가 이해하는대로 Android는 활동과 같은 메모리를 포함하는 프로세스를 회수합니다. 애플리케이션이 포함 된 프로세스가 종료되면 (Android가 그렇게 할 수 있다면?) 본질적으로 앱을 종료하는 것과 같습니다. 사용자는 앱을 다시 시작해야하며, 그 시점에서 누가 신경을 쓰나요? 애플리케이션의 새 인스턴스입니다.
Andrew

14
이것은 프로덕션에서 우리에게 불쾌한 놀라움이었습니다. Android가 프로세스를 종료한다고 믿으십시오. 문서에 설명 된 RAM 상태 및 기타 요인에 따라 다릅니다. 우리에게는 악몽 이었기 때문에 실제 경험을 공유합니다. 에뮬레이터에는이 기능이 없었지만 실제 세계에서는 일부 장치에 앱이 '과부화'되어 있으므로 백그라운드 프로세스를 종료하는 것은 정상적인 상황입니다. 예, 사용자가 앱을 포 그라운드로 설정하기로 결정하면 OS가 Application인스턴스를 포함한 스택을 복원 하지만 유지하지 않는 한 신뢰할 수있는 정적 데이터는 없습니다.
Vit Khudenko 2010

2
나는 아마도 하이브리드 접근 방식을 사용할 것이라고 생각합니다. 방향 변경을 재정의하는 매니페스트 트릭에 대해 이미 알고있었습니다 (다른 이점이 있음). 응용 프로그램이 게임이기 때문에 출시 사이에 데이터를 유지하는 것이 "중요"한지 확신 할 수 없습니다. 대부분의 데이터가 직렬화 될 수 있기 때문에 그렇게 어렵지는 않을 것입니다 (모든 방향 변경간에 직렬화 및 직렬화 해제하고 싶지는 않지만). 입력 해 주셔서 감사합니다. 나는 App 인스턴스에 의존하는 것이 "잘못되었다"고 말하지 않을 것입니다. 앱에 따라 많이 다릅니다.
Dave

1
@Arhimed 당신은 당신의 대답을 너무 많이 일반화하고 있습니다. 그리고 당신의 가정을 바탕으로 좁은 접근 방식을 제안합니다. 거짓 가정 : 정적 변수에 보관 된 데이터는 앱 세션 전체에서 유지되어야합니다. 데이터가 사소하고 즉시 유지할 필요가없는 많은 사용 사례가있을 수 있습니다.
Mandar Limaye

2
복잡한 구조의 약 1MB 데이터가 있습니다. 직렬화 / 역 직렬화는 장치가 작업으로 과부하 될 때 최대 2-3 초의 비용이들 수 있습니다. 활동 사이에 저장 /로드하는 아이디어는 너무 많은 시간이 소요됩니다. 나는 응용 프로그램을 저장소로 사용합니다. 물론 응용 프로그램 인스턴스에 저장된 데이터 클래스는 모든 메타 데이터를 확인합니다. 데이터가 아직 살아 있거나로드되어야합니다. 따라서 Dave는 다음을 수행해야합니다. 1.로드 / 저장 정보를 제공합니다. 2. 데이터를 애플리케이션에 보관합니다. 3. 데이터 액세스를위한 트리플 체크 로직.
Kostadin 2012-08-13

6

활동 외부의 "Global Singleton"에 액세스하고 싶고 Context관련된 모든 개체를 통과 하여 단일 항목을 얻지 않으려면 응용 프로그램 클래스에 정적 속성을 정의하기 만하면됩니다. 그 자체. onCreate()메소드 에서 속성을 초기화하십시오 .

예를 들면 :

public class ApplicationController extends Application {
    private static ApplicationController _appCtrl;

    public static ApplicationController getAppCtrl()
    {
         return _appCtrl;
    }
}

의 서브 클래스 Application도 리소스를 얻을 수 있으므로 다음과 같이 리소스를 반환하는 정적 메서드를 정의 할 때 간단히 액세스 할 수 있습니다.

public static Resources getAppResources()
{
    return _appCtrl.getResources();
}

그러나 메모리 누수방지 하기 위해 컨텍스트 참조를 전달할 때 매우주의 해야합니다 .


6
클래스를 인스턴스화하려면 매니페스트의 애플리케이션 태그에 android : name = ". ApplicationController"xml 속성을 추가해야한다는 점을 잊었습니다.
eggie5

이 작업 Application을 수행 하기 위해 실제로 확장 할 필요는 없습니다 . 이를 위해 모든 클래스 에서 정적 멤버 변수를 선언 할 수 있습니다 .
David Wasser

2

데이브, 어떤 종류의 데이터입니까? 애플리케이션 전체와 관련된 일반 데이터 (예 : 사용자 데이터) 인 경우 Application 클래스를 확장하여 여기에 저장합니다. 데이터가 활동과 관련된 경우 화면 회전시 데이터를 유지하려면 onSaveInstanceState 및 onRestoreInstanceState 핸들러를 사용해야합니다.


데이터가 Parcel에 저장하기에 정말 큰 경우 어떻게해야합니까? android.os.TransactionTooLargeException :이 메신저지고 무엇 데이터 소포 크기 838,396 바이트
아르 준 Issar

1

실제로 방향 기능을 재정 의하여 활동이 파괴되고 다시 생성되지 않도록 할 수 있습니다. 봐 여기 .


16
많은 일을 할 수 있습니다. 좋은 아이디어라는 뜻은 아닙니다. 이것은 좋은 생각이 아닙니다.
Andrew

화면 방향을 변경하여 테스트하는 것은 앱이 Android에서 가정하는 작업을 수행하는지 확인하는 가장 쉬운 방법입니다.
18446744073709551615

0

응용 프로그램 클래스를 만들고 응용 프로그램의 어디서나 사용할 수 있도록 해당 calss에 모든 데이터를 저장할 수 있습니다.


0

이것이 매우 오래된 질문이라는 것을 알고 있지만 jetpack 구성 요소ViewModel을 사용하는 것이 활동 회전 사이에 데이터를 보존하는 가장 좋은 방법입니다.

ViewModel 클래스는 수명주기를 고려하여 UI 관련 데이터를 저장하고 관리하도록 설계되었습니다. ViewModel 클래스를 사용하면 데이터가 화면 회전과 같은 구성 변경에서 살아남을 수 있습니다.

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