활동 간에 데이터를 공유하는 가장 좋은 방법은 무엇입니까?
앱 전체에서 사용되는 메인 액티비티인 액티비티가 하나 있는데, 그 액티비티는 여러 가지 변수가 있습니다.저는 첫 번째 활동에서 얻은 데이터를 사용할 수 있는 다른 두 가지 활동이 있습니다.이제 나는 다음과 같은 것을 할 수 있다는 것을 안다.
GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();
다만, 많은 변수를 공유하고 싶은 것도 있고, 큰 변수도 있을 수 있기 때문에 위와 같이 복사본을 만들고 싶지 않습니다.
get 및 set 방법을 사용하지 않고 변수를 직접 가져오고 변경할 수 있는 방법이 있습니까?구글 개발 사이트에서 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
.
디스크를 유지하지 않고 데이터 공유
대부분의 경우 두 액티비티가 동일한 프로세스로 실행된다는 점을 고려하면 액티비티를 메모리에 저장함으로써 액티비티비티를 메모리에 저장합니다.
참고: 사용자가 작업을 종료하지 않고 종료하면 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();
응용 프로그램 싱글톤 사용
은 singleton의 입니다.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를 전달해야 할 수도 있고 전달해야 할 수도 있습니다.모든 것은 당신의 특정한 문제에 달려있다.
개체를 디스크에 유지
다른 액티비티를 기동하기 전에, 데이터를 디스크에 보존하는 것이 목적입니다.
장점: 다른 장소에서 액티비티를 시작할 수 있습니다.데이터가 이미 유지되고 있다면 정상적으로 동작할 수 있습니다.
단점: 번거롭고 구현에 시간이 걸립니다.더 많은 코드가 필요하기 때문에 버그가 발생할 가능성이 높아집니다.그것은 또한 훨씬 더 느려질 것이다.
개체를 유지하는 방법에는 다음과 같은 것이 있습니다.
- 공유 기본 설정에 저장
- SQLite 데이터베이스에 저장
- 파일을 파일에 저장합니다(이 파일은 사용하지 않습니다).
사용할 수 있는 것:
- 활동 간 데이터 전달(Christian이 말한 것처럼)
- 많은 정적 변수를 포함하는 클래스를 사용합니다(따라서 클래스의 인스턴스 없이 getter/setter를 사용하지 않고 해당 변수를 호출할 수 있습니다).
- 데이터베이스 사용
- 공유 설정
당신이 무엇을 선택하느냐는 당신의 필요에 달려 있다.아마 '많이'가 있을 때 여러 가지 방법을 사용할 것입니다.
Google 명령대로 실행하세요!여기서 http://developer.android.com/resources/faq/framework.html#3
- 원시 데이터 유형
- 비영구 객체
- 싱글톤 수업 - 내가 제일 좋아하는 수업:d
- 퍼블릭 스태틱필드/방식
- 오브젝트에 대한 WeakReference 해시맵
- 영구 객체(어플리케이션 설정, 파일, 콘텐츠 제공자, SQLite DB)
"다만 저는 많은 변수를 공유하고 싶고, 일부는 상당히 클 수 있기 때문에 위와 같은 변수 복사본을 만들고 싶지 않습니다."
이렇게 하면 복사가 되지 않습니다(특히 String에서는 오브젝트도 오브젝트 자체가 아니라 참조의 값으로 전달됩니다.게터도 사용할 수 있습니다.일반적이고 잘 이해되고 있기 때문에 다른 수단보다 사용하는 것이 좋습니다).getter와 setter를 사용하지 않는 것과 같은 오래된 "퍼포먼스 신화"는 여전히 어느 정도 가치가 있지만 문서에서도 업데이트되었습니다.
그러나 원하지 않는 경우에는 변수를 GlobalState에서 공개 또는 보호하여 직접 액세스할 수도 있습니다.또한 응용프로그램 개체 JavaDoc이 나타내는 정적 싱글톤을 만들 수 있습니다.
통상, 애플리케이션을 서브 클래스 할 필요는 없습니다.대부분의 경우 스태틱싱글톤은 같은 기능을 모듈러 방식으로 제공할 수 있습니다.싱글톤에 글로벌콘텍스트가 필요한 경우(예를 들어 브로드캐스트리시버를 등록하기 위해), 이 콘텍스트를 취득하는 함수에 Context.getApplicationContext()를 사용하여 싱글톤을 최초로 구축할 수 있습니다.
다른 답변과 같이 의도 데이터를 사용하는 것도 데이터를 전달하는 다른 방법이지만 일반적으로 더 작은 데이터나 단순한 유형에 사용됩니다.대용량/복잡한 데이터를 전달할 수 있지만 정적 싱글론을 사용하는 것 이상의 작업이 필요합니다.응용 프로그램 개체는 Android 응용 프로그램 구성 요소 간에 더 크고 복잡한 비영구적인 데이터를 공유할 때 여전히 개인적으로 가장 좋아합니다(Android 응용 프로그램에는 라이프 사이클이 잘 정의되어 있기 때문입니다).
또한 다른 사용자가 지적한 바와 같이 데이터가 매우 복잡하여 영속성이 필요한 경우 SQLite 또는 파일 시스템을 사용할 수도 있습니다.
활동 간에 데이터를 공유할 수 있는 새롭고 더 나은 방법이 있습니다. 바로 LiveData입니다.특히 Android 개발자 페이지의 다음 인용문에 주목하십시오.
LiveData 객체가 라이프 사이클 인식이라는 것은 여러 활동, 단편화 및 서비스 간에 공유할 수 있음을 의미합니다.예를 단순하게 하기 위해 LiveData 클래스를 싱글톤으로 구현할 수 있습니다.
은 매우를 가지고 모델 데이터라도 될 수 .LiveData
에서 각각의 활동에 될 수 .ViewModel
험성시메모리 누수를 방지하기 위해 더 이상 취약한 참조에 대해 걱정할 필요가 없습니다.
응용 프로그램 클래스를 확장하고 원하는 개체에 태그를 지정할 수 있습니다. 그러면 응용 프로그램 내 어디에서나 개체를 사용할 수 있습니다.
액티비티간에 데이터를 공유하는 방법은 다양합니다.
1: 의도를 사용한 활동 간 데이터 전달
Intent intent=new Intent(this, desirableActivity.class);
intent.putExtra("KEY", "Value");
startActivity(intent)
2: static 키워드를 사용하여 변수를 public static으로 정의하고 anywhere in project를 사용합니다.
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();
위에서 설명한 약한 참조 접근법 및 http://developer.android.com/guide/faq/framework.html의 해시맵을 사용하는 것은 문제가 있는 것 같습니다.맵 값뿐만 아니라 엔트리 전체가 어떻게 회수됩니까?어떤 범위에 할당하고 있습니까?프레임워크가 액티비티 라이프 사이클을 제어하기 때문에 참여 액티비티 중 하나를 소유하게 되면 소유자가 클라이언트보다 먼저 파괴될 때 런타임 오류가 발생할 위험이 있습니다.응용 프로그램이 해당 엔트리를 소유하고 있는 경우 일부 액티비티는 해시맵이 유효한 키와 수집된 취약한 참조를 가진 엔트리를 유지하지 않도록 엔트리를 명시적으로 삭제해야 합니다.또한 키에 대해 반환된 값이 null일 경우 클라이언트는 어떻게 해야 합니까?
어플리케이션 소유의 Weak Hash Map 또는 싱글톤 내의 Weak Hash Map이 더 나은 선택인 것 같습니다.맵 내의 값은 키 오브젝트를 통해 액세스 됩니다.키에 대한 강력한 참조가 존재하지 않는 경우(즉, 모든 액티비티가 키와 맵의 대상으로 실행됨), GC는 맵엔트리를 회수할 수 있습니다.
글쎄요, 몇 가지 아이디어가 있긴 한데, 그게 당신이 원하는 건지 모르겠네요.
모든 데이터를 보관하는 서비스를 사용하여 작업을 서비스에 바인딩하여 데이터 취득을 수행할 수 있습니다.
또는 데이터를 직렬화 가능 또는 분할 가능한 형태로 패키징하여 번들에 연결하고 작업 간에 번들을 전달합니다.
이것은 원하는 것과는 전혀 다를 수 있지만 Shared Preferences 또는 일반 Preferences를 사용해 볼 수도 있습니다.
어느 쪽이든 결정 사항을 알려주세요.
의도를 사용하여 활동 1에서 활동 2를 호출한다고 가정합니다.
intention.putExtra()를 사용하여 데이터를 전달할 수 있습니다.
이것을 참고하세요.Intent.putExtra를 사용하여 어레이 전송
그게 네가 원하는 것이길 바래.
현재 활동에서 다른 활동을 호출하려면 Intents를 사용해야 합니다.데이터 유지보다는 필요에 따라 데이터를 공유하는 데 초점을 맞출 수 있습니다.
그러나 이러한 값을 유지해야 하는 경우에는 로컬 스토리지의 구조화된 텍스트 파일이나 데이터베이스에 값을 유지할 수 있습니다.속성 파일, XML 파일 또는 JSON 파일은 데이터를 저장하고 활동 생성 중에 쉽게 구문 분석할 수 있습니다.또한 모든 Android 기기에 SQLite가 있으므로 데이터베이스 테이블에 저장할 수 있습니다.맵을 사용하여 키-값 쌍을 저장하고 맵을 로컬 스토리지로 직렬화할 수도 있지만, 이는 너무 복잡하여 단순한 데이터 구조에는 유용할 수 없습니다.
위의 답변은 모두 훌륭합니다.액티비티를 통해 데이터를 유지하는 것에 대해 아직 아무도 언급하지 않은 것 중 하나를 덧붙입니다.즉, Android SQLite 내장 데이터베이스를 사용하여 관련 데이터를 유지하는 것입니다.실제로 데이터베이스를 배치할 수 있습니다.어플리케이션 상태에 있는 도우미 및 액티비티 전체에서 필요에 따라 호출합니다.또는 도우미 클래스를 만들고 필요할 때 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를 구현하면 자동으로 Serialize됩니다.
- Parchable은 안드로이드 자체 직렬화 프로토콜입니다.Parchable에서 개발자는 마샬링 및 마샬링 해제용 커스텀 코드를 작성합니다.따라서 시리얼라이제이션에 비해 가비지 오브젝트를 적게 생성됩니다.
- 커스텀 구현으로 인해 Serialable과 비교할 때 성능이 매우 우수하며 Android에서 객체를 Serialization할 때 Parcelable inpartition을 사용하는 것이 좋습니다.
public class User implements Parcelable
여기에서 더 자세히 확인하세요.
언급URL : https://stackoverflow.com/questions/4878159/whats-the-best-way-to-share-data-between-activities
'programing' 카테고리의 다른 글
Vuex와 Redux의 불변성 접근방식의 차이점 (0) | 2022.07.26 |
---|---|
여러 vuex createNamesched에 대한 베스트 프랙티스는 무엇입니까?도우미? (0) | 2022.07.26 |
Vuex의 상태 초기화 코드를 어디에 넣어야 합니까? (0) | 2022.07.26 |
iOS 라이브러리에서 BitCode로 (0) | 2022.07.26 |
이 C는 왜 유효합니까? (0) | 2022.07.26 |