활동간에 데이터를 공유하는 가장 좋은 방법은 무엇입니까?
앱 전체에서 사용되는 주요 활동 인 하나의 활동이 있으며 여러 변수가 있습니다. 첫 번째 활동의 데이터를 사용할 수있는 두 가지 다른 활동이 있습니다. 이제 다음과 같이 할 수 있다는 것을 알고 있습니다.
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 String 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를 전달해야 할 수도 있고 아닐 수도 있습니다. 그것은 모두 특정 문제에 달려 있습니다.
디스크에 객체 유지
아이디어는 다른 활동을 시작하기 전에 디스크에 데이터를 저장하는 것입니다.
장점 : 다른 곳에서 활동을 시작할 수 있으며 데이터가 이미 지속되면 제대로 작동합니다.
단점 : 번거롭고 구현하는 데 시간이 더 걸립니다. 더 많은 코드가 필요하므로 버그가 발생할 가능성이 높습니다. 또한 훨씬 느려질 것입니다.
객체를 유지하는 몇 가지 방법은 다음과 같습니다.
- 공유 환경 설정에 저장
- sqlite 데이터베이스에 저장하십시오
- 파일로 저장하십시오 (이것을 피할 것입니다)
사용할 수있는 것 :
- 활동간에 데이터 전달 (Cristian이 말한 것처럼)
- 정적 변수가 많은 클래스 사용 (클래스 인스턴스없이 getter / setter를 사용하지 않고 호출 할 수 있음)
- 데이터베이스 사용
- 공유 환경 설정
선택하는 것은 필요에 따라 다릅니다. 아마도 당신은 "많이"있을 때 하나 이상의 방법을 사용할 것입니다
당신이 구글 명령을 수행하십시오! 여기 : http://developer.android.com/resources/faq/framework.html#3
- 기본 데이터 유형
- 비 영구 객체
- 싱글턴 수업-내가 좋아하는 것 : D
- 공개 정적 필드 / 방법
- 객체에 대한 약한 참조의 HashMap
- 영구 객체 (응용 프로그램 환경 설정, 파일, contentProviders, SQLite DB)
"그러나 많은 변수를 공유하고 싶고 일부는 다소 클 수 있으므로 위와 같이 사본을 만들고 싶지 않습니다."
그것은 복사를하지 않습니다 (특히 String 을 사용하지만 객체조차도 객체 자체가 아닌 참조 값을 전달합니다. 게터는 사용하기에 좋습니다. 공통적이고 다른 방법보다 사용하는 것이 더 좋습니다) 잘 이해했습니다). getter 및 setter를 사용하지 않는 것과 같은 오래된 "성능 신화"는 여전히 가치가 있지만 docs에서도 업데이트되었습니다 .
그러나 그렇게하고 싶지 않으면 GlobalState 에서 변수를 공개하거나 보호 하여 직접 액세스 할 수도 있습니다. 또한 Application 객체 JavaDoc이 나타내는 대로 정적 싱글 톤을 만들 수 있습니다 .
일반적으로 Application을 서브 클래 싱 할 필요는 없습니다. 대부분의 상황에서 정적 싱글 톤은보다 기능적인 방식으로 동일한 기능을 제공 할 수 있습니다. 싱글 톤에 글로벌 컨텍스트가 필요한 경우 (예 : 브로드 캐스트 수신기 등록) 싱글 톤을 처음 생성 할 때 내부적으로 Context.getApplicationContext ()를 사용하는 컨텍스트를 검색하는 함수를 검색 할 수 있습니다.
다른 답변에서 언급 했듯이 인 텐트 데이터를 사용하면 데이터를 전달하는 또 다른 방법이지만 일반적으로 더 작은 데이터 및 간단한 유형에 사용됩니다. 더 크고 복잡한 데이터를 전달할 수 있지만 정적 싱글 온을 사용하는 것보다 더 복잡합니다. 응용 프로그램 객체는 여전히 (이 안드로이드 응용 프로그램에서 잘 정의 된 라이프 사이클을 가지고 있기 때문에)하지만 안드로이드 응용 프로그램 구성 요소 사이에 큰 / 더 복잡한 비 영구 데이터를 공유하기위한 내 개인 좋아하는 것입니다.
또한 다른 사람들이 지적했듯이 데이터가 매우 복잡 하고 지속적이어야 하는 경우 SQLite 또는 파일 시스템을 사용할 수 있습니다.
Application 클래스를 확장하고 원하는 객체에 태그를 지정하면 응용 프로그램의 어느 곳에서나 사용할 수 있습니다
위에서 설명한 http://developer.android.com/guide/faq/framework.html 에서 약한 참조 방식의 해시 맵을 사용하면 문제가되는 것 같습니다. 맵 값뿐만 아니라 전체 항목을 어떻게 회수합니까? 어떤 범위에 할당합니까? 프레임 워크가 활동 라이프 사이클을 제어하므로 참여 활동 중 하나를 소유하면 소유자가 클라이언트보다 먼저 소멸 될 때 런타임 오류가 발생할 위험이 있습니다. 응용 프로그램이이를 소유 한 경우, 일부 활동은 해시 맵이 유효한 키와 잠재적으로 가비지 수집 된 약한 참조를 가진 항목을 보유하지 않도록 항목을 명시 적으로 제거해야합니다. 또한 키에 대해 반환 된 값이 null 인 경우 클라이언트는 어떻게해야합니까?
응용 프로그램이 소유하거나 단일 톤 내에있는 WeakHashMap이 더 나은 선택 인 것 같습니다. 지도의 값은 키 객체를 통해 액세스되며 키에 대한 강력한 참조가 존재하지 않는 경우 (즉, 모든 활동이 키와 매핑 된 것으로 수행됨) GC는지도 항목을 회수 할 수 있습니다.
활동간에 데이터를 공유하는 다양한 방법이 있습니다
1 : 의도를 사용하여 활동간에 데이터 전달
Intent intent=new Intent(this, desirableActivity.class);
intent.putExtra("KEY", "Value");
startActivity(intent)
2 : static 키워드를 사용하여 변수를 public static으로 정의하고 프로젝트의 모든 위치를 사용하십시오.
public static int sInitialValue=0;
classname.variableName을 사용하여 프로젝트의 어느 곳에서나 사용하십시오.
3 : 데이터베이스 사용
그러나 비트 프로세스가 길면 쿼리를 사용하여 데이터를 삽입하고 필요할 때 커서를 사용하여 데이터를 반복해야합니다. 그러나 캐시를 정리하지 않고 데이터를 잃을 가능성은 없습니다.
4 : 공유 환경 설정 사용
데이터베이스보다 훨씬 쉽습니다. 그러나 ArrayList, List 및 custome 객체를 저장할 수없는 몇 가지 제한 사항이 있습니다.
5 : Aplication 클래스에서 getter setter를 작성하고 프로젝트의 모든 위치에 액세스하십시오.
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
여기에 설정하고 활동에서 얻을
((YourApplicationClass)getApplicationContext()).setData("abc");
String data=((YourApplicationClass)getApplicationContext()).getData();
활동간에 데이터를 공유하는 새롭고 더 나은 방법이 있으며 LiveData 입니다. 특히 Android 개발자 페이지에서이 인용문을 확인하십시오.
LiveData 개체가 수명주기를 인식한다는 사실은 여러 활동, 조각 및 서비스간에 개체를 공유 할 수 있음을 의미합니다. 예제를 단순하게 유지하기 위해 LiveData 클래스를 싱글 톤으로 구현할 수 있습니다.
이것의 의미는 엄청납니다. 모든 모델 데이터는 LiveData
래퍼 내부의 일반적인 싱글 톤 클래스에서 공유 될 수 있습니다 . ViewModel
테스트 가능성을 위해 액티비티에서 각각으로 주입 될 수 있습니다 . 더 이상 메모리 누수를 방지하기 위해 약한 참조에 대해 걱정할 필요가 없습니다.
글쎄, 나는 몇 가지 아이디어가 있지만 그들이 당신이 찾고있는 것인지 모르겠다.
모든 데이터를 보유한 서비스를 사용한 다음 데이터 검색을 위해 활동을 서비스에 바인딩 할 수 있습니다.
또는 데이터를 직렬화 가능 또는 소포 가능으로 패키지하여 번들에 첨부하고 활동 사이에 번들을 전달하십시오.
이것은 당신이 찾고있는 것이 아닐 수도 있지만, SharedPreferences 또는 환경 설정을 일반적으로 사용해 볼 수도 있습니다.
어느 쪽이든 당신이 결정한 것을 알려주십시오.
인 텐트를 사용하여 활동 1에서 활동 2를 호출한다고 가정하십시오.
intent.putExtra ()를 사용하여 데이터를 전달할 수 있습니다.
이것을 참조하십시오. Intent.putExtra를 사용하여 배열 보내기
그것이 당신이 원하는 희망입니다.
당신의 의도가 현재의 활동에서 다른 활동을 호출하는 경우, 당신은 사용해야 텐트를 . 필요에 따라 데이터를 공유하는 것보다 데이터를 유지하는 데 집중할 수 없습니다.
그러나 이러한 값을 실제로 유지해야하는 경우 로컬 저장소의 일종의 구조화 된 텍스트 파일 또는 데이터베이스에 유지할 수 있습니다. 특성 파일, XML 파일 또는 JSON 파일은 데이터를 저장하고 활동 작성 중에 쉽게 구문 분석 할 수 있습니다. 모든 Android 장치에 SQLite가 있으므로 데이터베이스 테이블에 저장할 수 있습니다. 맵을 사용하여 키-값 쌍을 저장하고 맵을 로컬 스토리지에 직렬화 할 수도 있지만 간단한 데이터 구조에는 유용하지 않을 수 있습니다.
위에서 언급 한 모든 대답은 훌륭합니다 ... 활동을 통해 데이터를 유지하는 것에 대해 아직 언급하지 않은 사람을 추가하고 있습니다. 즉, 내장 된 Android SQLite 데이터베이스를 사용하여 관련 데이터를 유지하는 것입니다 ... 사실 당신은 응용 프로그램 상태의 databaseHelper를 활성화하고 활성화하는 동안 필요에 따라 호출하십시오. 또는 도우미 클래스를 만들고 필요할 때 DB를 호출하십시오 ... 다른 레이어를 추가하기 만하면됩니다. 그러나 다른 모든 답변으로 충분합니다. 뿐만 아니라 .. 정말 선호
로그인 후 이메일을 전달하는 활동 사이의 데이터 공유 예
"이메일"은 요청중인 활동의 값을 참조하는 데 사용할 수있는 이름입니다.
로그인 페이지의 1 코드
Intent openLoginActivity = new Intent(getBaseContext(), Home.class);
openLoginActivity.putExtra("email", getEmail);
홈페이지의 2 개 코드
Bundle extras = getIntent().getExtras();
accountEmail = extras.getString("email");
그리고 데이터 객체로 작업하고 싶다면이 두 가지 구현이 매우 중요합니다.
직렬화 가능 및 소포 가능
- Serializable은 마커 인터페이스로, 사용자는 요구 사항에 따라 데이터를 마샬링 할 수 없습니다. 따라서 객체가 Serializable을 구현하면 Java가 자동으로 직렬화합니다.
- Parcelable은 안드로이드 자체 직렬화 프로토콜입니다. Parcelable에서 개발자는 마샬링 및 마샬링 해제를위한 사용자 지정 코드를 작성합니다. 따라서 직렬화에 비해 가비지 객체가 적습니다.
- Parcelable의 성능은 사용자 지정 구현으로 인해 Serializable과 비교할 때 매우 높습니다. Android에서 객체를 직렬화 할 때 Parcelable 주입을 사용하는 것이 좋습니다.
public class User implements Parcelable
참고 URL : https://stackoverflow.com/questions/4878159/whats-the-best-way-to-share-data-between-activities
'Programing' 카테고리의 다른 글
.NET을 사용하면 확장자가 아닌 파일 서명을 기반으로 파일의 MIME 유형을 찾는 방법 (0) | 2020.04.15 |
---|---|
배열이 비어 있는지 확인 (0) | 2020.04.15 |
변수 이름이 종종 문자 'm'으로 시작하는 이유는 무엇입니까? (0) | 2020.04.15 |
문자열 구분 기호로 문자열을 어떻게 나눌 수 있습니까? (0) | 2020.04.15 |
컨텍스트 또는 활동 외부의 getString (0) | 2020.04.15 |