[java] 활동간에 데이터를 공유하는 가장 좋은 방법은 무엇입니까?

앱 전체에서 사용되는 주요 활동 인 하나의 활동이 있으며 여러 변수가 있습니다. 첫 번째 활동의 데이터를 사용할 수있는 두 가지 다른 활동이 있습니다. 이제 다음과 같이 할 수 있다는 것을 알고 있습니다.

GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();

그러나 나는 많은 변수를 공유하고 싶고 일부는 다소 클 수 있으므로 위와 같이 사본을 만들고 싶지 않습니다.

get 및 set 메소드를 사용하지 않고 변수를 직접 가져오고 변경하는 방법이 있습니까? Google 개발자 사이트에서 Android에서의 성능에 권장되지 않는 기사를 읽은 것을 기억합니다.



답변

여기에 이것을 달성하는 가장 일반적인 방법 의 편집 :

  • 의도 내에서 데이터 보내기
  • 정적 필드
  • 해시지도 WeakReferences
  • 객체 유지 (sqlite, 공유 환경 설정, 파일 등)

TL; DR : 데이터를 공유하는 두 가지 방법이 있습니다 : 데이터를 인 텐트로 전달하거나 다른 곳에 저장하는 것. 데이터가 기본 요소, 문자열 또는 사용자 정의 오브젝트 인 경우 : 의도 추가 항목의 일부로 전송하십시오 (사용자 정의 오브젝트는을 구현해야합니다 Parcelable). 복잡한 객체를 전달하는 경우 인스턴스를 다른 곳에 싱글 톤으로 저장하고 시작된 액티비티에서 액세스합니다.

각 접근 방식을 구현하는 방법과 이유에 대한 몇 가지 예 :

의도 내에서 데이터 보내기

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);

두 번째 활동에서 :

Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");

기본 데이터 또는 문자열을 전달하는 경우이 방법을 사용하십시오 . 또한 구현하는 객체를 전달할 수도 있습니다 Serializable.

유혹적이지만 사용하기 전에 두 번 생각해야합니다 Serializable. 오류가 발생하기 쉽고 엄청나게 느립니다. 따라서 일반적으로 가능하면 멀리Serializable 하십시오. 복잡한 사용자 정의 객체를 전달 하려면 Parcelable인터페이스를 살펴보십시오 . 구현하기는 어렵지만에 비해 상당한 속도 향상이 Serializable있습니다.

디스크를 유지하지 않고 데이터 공유

대부분의 경우 두 활동이 동일한 프로세스에서 실행되는 경우 메모리에 저장하여 활동간에 데이터를 공유 할 수 있습니다.

참고 : 때때로 사용자가 활동을 종료하지 않고 종료 할 때 (Android는) 응용 프로그램을 종료하기로 결정할 수 있습니다. 이러한 시나리오에서 안드로이드가 앱이 종료되기 전에 제공된 의도를 사용하여 마지막 활동을 시작하려는 경우를 경험했습니다. 이 경우 싱글 톤 (귀하의 또는 Application)에 저장된 데이터 는 사라지고 나쁜 일이 발생할 수 있습니다. 이러한 경우를 피하려면 오브젝트를 디스크에 지속 시키거나 사용하기 전에 데이터를 점검하여 유효한지 확인하십시오.

싱글 톤 클래스 사용

데이터를 보관할 수업을 준비하십시오.

public class DataHolder {
  private String data;
  public String getData() {return data;}
  public void setData(String data) {this.data = data;}

  private static final DataHolder holder = new DataHolder();
  public static DataHolder getInstance() {return holder;}
}

시작된 활동에서 :

String data = DataHolder.getInstance().getData();

응용 프로그램 싱글 톤 사용

응용 프로그램 싱글 톤은 android.app.Application앱이 시작될 때 생성 되는 인스턴스입니다 . 다음을 확장하여 사용자 정의 항목을 제공 할 수 있습니다 Application.

import android.app.Application;
public class MyApplication extends Application {
  private String data;
  public String getData() {return data;}
  public void setData(String data) {this.data = data;}
}

활동을 시작하기 전에 :

MyApplication app = (MyApplication) getApplicationContext();
app.setData(someData);

그런 다음 시작된 활동에서 :

MyApplication app = (MyApplication) getApplicationContext();
String data = app.getData();

정적 필드

아이디어는 기본적으로 싱글 톤과 동일하지만이 경우 데이터에 정적 액세스를 제공합니다.

public class DataHolder {
  private static String data;
  public static String getData() {return data;}
  public static void setData(String data) {DataHolder.data = data;}
}

시작된 활동에서 :

String data = DataHolder.getData();

해시지도 WeakReferences

같은 생각이지만 가비지 수집기가 참조되지 않은 객체를 제거하도록 허용 (예 : 사용자가 활동을 종료 한 경우)

public class DataHolder {
  Map<String, WeakReference<Object>> data = new HashMap<String, WeakReference<Object>>();

  void save(String id, Object object) {
    data.put(id, new WeakReference<Object>(object));
  }

  Object retrieve(String id) {
    WeakReference<Object> objectWeakReference = data.get(id);
    return objectWeakReference.get();
  }
}

활동을 시작하기 전에 :

DataHolder.getInstance().save(someId, someObject);

시작된 활동에서 :

DataHolder.getInstance().retrieve(someId);

인 텐트의 엑스트라를 사용하여 객체 ID를 전달해야 할 수도 있고 아닐 수도 있습니다. 그것은 모두 특정 문제에 달려 있습니다.

디스크에 객체 유지

아이디어는 다른 활동을 시작하기 전에 디스크에 데이터를 저장하는 것입니다.

장점 : 다른 곳에서 활동을 시작할 수 있으며 데이터가 이미 지속되면 제대로 작동합니다.

단점 : 번거롭고 구현하는 데 시간이 더 걸립니다. 더 많은 코드가 필요하므로 버그가 발생할 가능성이 높습니다. 또한 훨씬 느려질 것입니다.

객체를 유지하는 몇 가지 방법은 다음과 같습니다.


답변

사용할 수있는 것 :

  1. 활동간에 데이터 전달 (Cristian이 말한 것처럼)
  2. 정적 변수가 많은 클래스 사용 (클래스 인스턴스없이 getter / setter를 사용하지 않고 호출 할 수 있음)
  3. 데이터베이스 사용
  4. 공유 환경 설정

당신이 선택하는 것은 당신의 필요에 달려 있습니다. 아마도 당신은 “많이”있을 때 하나 이상의 방법을 사용할 것입니다


답변

당신이 구글 명령을 수행하십시오! 여기 : http://developer.android.com/resources/faq/framework.html#3

  • 기본 데이터 유형
  • 비 영구 객체
  • 싱글턴 수업-내가 좋아하는 것 : D
  • 공개 정적 필드 / 방법
  • 객체에 대한 약한 참조의 HashMap
  • 영구 객체 (응용 프로그램 환경 설정, 파일, contentProviders, SQLite DB)

답변

“그러나 많은 변수를 공유하고 싶고 일부는 다소 클 수 있으므로 위와 같이 사본을 만들고 싶지 않습니다.”

그것은 복사를하지 않습니다 (특히 String 을 사용하지만 객체조차도 객체 자체가 아닌 참조 값으로 전달되며 getter는 사용하기에 적합합니다. 공통적이고 다른 방법보다 사용하는 것이 더 좋습니다) 잘 이해했습니다). getter 및 setter를 사용하지 않는 것과 같은 오래된 “성능 신화”는 여전히 가치가 있지만 docs에서도 업데이트되었습니다 .

그러나 그렇게하고 싶지 않으면 GlobalState 에서 변수를 공개하거나 보호 하여 직접 액세스 할 수도 있습니다. 또한 Application 객체 JavaDoc이 나타내는 대로 정적 싱글 톤을 만들 수 있습니다 .

일반적으로 Application을 서브 클래 싱 할 필요가 없습니다. 대부분의 상황에서 정적 싱글 톤은보다 기능적인 방식으로 동일한 기능을 제공 할 수 있습니다. 싱글 톤에 글로벌 컨텍스트가 필요한 경우 (예 : 브로드 캐스트 수신기 등록) 싱글 톤을 처음 생성 할 때 내부적으로 Context.getApplicationContext ()를 사용하는 컨텍스트를 검색하는 함수를 검색 할 수 있습니다.

다른 답변에서 언급 했듯이 인 텐트 데이터를 사용하면 데이터를 전달하는 또 다른 방법이지만 일반적으로 작은 데이터 및 간단한 유형에 사용됩니다. 더 크고 복잡한 데이터를 전달할 수 있지만 정적 싱글 온을 사용하는 것보다 더 복잡합니다. 응용 프로그램 객체는 여전히 (이 안드로이드 응용 프로그램에서 잘 정의 된 라이프 사이클을 가지고 있기 때문에)하지만 안드로이드 응용 프로그램 구성 요소 사이에 큰 / 더 복잡한 비 영구 데이터를 공유하기위한 내 개인 좋아하는 것입니다.

또한 다른 사람들이 지적했듯이 데이터가 매우 복잡 하고 지속적이어야 하는 경우 SQLite 또는 파일 시스템을 사용할 수 있습니다.


답변

Application 클래스를 확장하고 원하는 객체에 태그를 지정하면 응용 프로그램의 어느 곳에서나 사용할 수 있습니다


답변

활동간에 데이터를 공유하는 새롭고 더 나은 방법이 있으며 LiveData 입니다. 특히 Android 개발자 페이지에서이 인용문을 확인하십시오.

LiveData 객체가 수명주기를 인식한다는 사실은 여러 활동, 프래그먼트 및 서비스간에 객체를 공유 할 수 있음을 의미합니다. 예제를 단순하게 유지하기 위해 LiveData 클래스를 싱글 톤으로 구현할 수 있습니다.

이것의 의미는 엄청납니다. 모든 모델 데이터는 LiveData래퍼 내부의 일반적인 싱글 톤 클래스에서 공유 될 수 있습니다 . ViewModel테스트 가능성을 위해 액티비티에서 각각으로 주입 될 수 있습니다 . 더 이상 메모리 누수를 방지하기 위해 약한 참조에 대해 걱정할 필요가 없습니다.


답변

위에서 설명한 http://developer.android.com/guide/faq/framework.html 에서 약한 참조 방식의 해시 맵을 사용하면 문제가되는 것 같습니다. 맵 값뿐만 아니라 전체 항목을 어떻게 회수합니까? 어떤 범위에 할당합니까? 프레임 워크가 활동 라이프 사이클을 제어하므로 참여 활동 중 하나를 소유하면 소유자가 클라이언트보다 먼저 소멸 될 때 런타임 오류가 발생할 위험이 있습니다. 애플리케이션이이를 소유 한 경우, 일부 활동은 해시 맵이 유효한 키와 잠재적으로 가비지 수집 된 약한 참조를 가진 항목을 보유하지 않도록 항목을 명시 적으로 제거해야합니다. 또한 키에 대해 반환 된 값이 null 인 경우 클라이언트는 어떻게해야합니까?

응용 프로그램이 소유하거나 단일 톤 내에있는 WeakHashMap이 더 나은 선택 인 것 같습니다. 지도의 값은 키 객체를 통해 액세스되며 키에 대한 강력한 참조가 존재하지 않는 경우 (즉, 모든 활동이 키와 매핑 된 것으로 수행됨) GC는지도 항목을 회수 할 수 있습니다.