인텐트(최적의 솔루션)를 통해 열거나 개체 전달
시작할 때 두 개의 서로 다른 배열 목록에 액세스해야 하는 활동이 있습니다.두 목록은 모두 내가 직접 만든 다른 개체입니다.
기본적으로 이러한 개체를 의도에서 활동으로 전달하는 방법이 필요합니다.addExtra()를 사용할 수 있지만 이를 위해서는 Parcise 호환 클래스가 필요합니다.저는 제 수업이 연속적으로 통과되도록 만들 수 있지만, 제가 이해하기로는 이것이 프로그램을 느리게 합니다.
제가 선택할 수 있는 방법이 무엇입니까?
열거형을 통과할 수 있습니까?
별도로, 의도에서 활동 생성자에게 매개변수를 전달할 수 있는 방법이 있습니까?
이것은 오래된 질문이지만, 모든 사람들은 에넘이 실제로Serializable
따라서 의도에 추가로 완벽하게 추가될 수 있습니다.다음과 같이:
public enum AwesomeEnum {
SOMETHING, OTHER;
}
intent.putExtra("AwesomeEnum", AwesomeEnum.SOMETHING);
AwesomeEnum result = (AwesomeEnum) intent.getSerializableExtra("AwesomeEnum");
정적 변수 또는 응용 프로그램 전체 변수를 사용하자는 제안은 정말 좋지 않은 생각입니다.이것은 실제로 여러분의 활동을 상태 관리 시스템에 연결하고, 유지보수, 디버그 및 문제 제한이 어렵습니다.
대안:
tedzyc는 Oderik이 제공하는 솔루션이 오류를 제공한다는 사실에 대해 좋은 점을 주목했습니다.그러나 제공되는 대안은 (일반 제품을 사용하더라도) 사용하기에 다소 번거롭습니다.
Entit에 열거형을 추가할 때의 성능이 정말 걱정된다면 대신 다음과 같은 대안을 제안합니다.
옵션 1:
public enum AwesomeEnum {
SOMETHING, OTHER;
private static final String name = AwesomeEnum.class.getName();
public void attachTo(Intent intent) {
intent.putExtra(name, ordinal());
}
public static AwesomeEnum detachFrom(Intent intent) {
if(!intent.hasExtra(name)) throw new IllegalStateException();
return values()[intent.getIntExtra(name, -1)];
}
}
용도:
// Sender usage
AwesomeEnum.SOMETHING.attachTo(intent);
// Receiver usage
AwesomeEnum result = AwesomeEnum.detachFrom(intent);
옵션 2: (일반적이고 재사용 가능하며 열거형에서 분리됨)
public final class EnumUtil {
public static class Serializer<T extends Enum<T>> extends Deserializer<T> {
private T victim;
@SuppressWarnings("unchecked")
public Serializer(T victim) {
super((Class<T>) victim.getClass());
this.victim = victim;
}
public void to(Intent intent) {
intent.putExtra(name, victim.ordinal());
}
}
public static class Deserializer<T extends Enum<T>> {
protected Class<T> victimType;
protected String name;
public Deserializer(Class<T> victimType) {
this.victimType = victimType;
this.name = victimType.getName();
}
public T from(Intent intent) {
if (!intent.hasExtra(name)) throw new IllegalStateException();
return victimType.getEnumConstants()[intent.getIntExtra(name, -1)];
}
}
public static <T extends Enum<T>> Deserializer<T> deserialize(Class<T> victim) {
return new Deserializer<T>(victim);
}
public static <T extends Enum<T>> Serializer<T> serialize(T victim) {
return new Serializer<T>(victim);
}
}
용도:
// Sender usage
EnumUtil.serialize(AwesomeEnum.Something).to(intent);
// Receiver usage
AwesomeEnum result =
EnumUtil.deserialize(AwesomeEnum.class).from(intent);
옵션 3(Kotlin 사용):
시간이 꽤 흘렀지만, 이제 코틀린이 생겼기 때문에, 저는 새로운 패러다임을 위한 다른 옵션을 추가할 것이라고 생각했습니다.여기서는 확장 함수와 재지정된 유형(컴파일할 때 유형을 유지함)을 사용할 수 있습니다.
inline fun <reified T : Enum<T>> Intent.putExtra(victim: T): Intent =
putExtra(T::class.java.name, victim.ordinal)
inline fun <reified T: Enum<T>> Intent.getEnumExtra(): T? =
getIntExtra(T::class.java.name, -1)
.takeUnless { it == -1 }
?.let { T::class.java.enumConstants[it] }
이런 식으로 하면 몇 가지 이점이 있습니다.
- 직렬화를 수행하기 위해 중간 개체의 "오버헤드"가 필요하지 않습니다. 이는 모든 것이 제자리에서 수행되기 때문입니다.
inline
호출을 함수 내부의 코드로 대체합니다. - SDK와 기능이 비슷하기 때문에 더욱 친숙합니다.
- IDE는 이러한 기능을 자동으로 완료하므로 유틸리티 클래스에 대한 사전 지식이 필요하지 않습니다.
단점 중 하나는, 우리가 에움의 순서를 바꾸면, 오래된 참조가 작동하지 않는다는 것입니다.이것은 업데이트에서 살아남을 수 있기 때문에 보류 중인 의도 내부와 같은 문제가 될 수 있습니다.하지만, 나머지 시간 동안은 괜찮을 것입니다.
위치 대신 이름을 사용하는 것과 같은 다른 솔루션도 값의 이름을 바꾸면 실패합니다.그러나 이러한 경우 잘못된 Enum 값 대신 예외가 발생합니다.
용도:
// Sender usage
intent.putExtra(AwesomeEnum.SOMETHING)
// Receiver usage
val result = intent.getEnumExtra<AwesomeEnum>()
열거형을 구현할 수 있는 Parcelable을 만들 수 있습니다. 열거형은 매우 쉽습니다.
public enum MyEnum implements Parcelable {
VALUE;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(ordinal());
}
public static final Creator<MyEnum> CREATOR = new Creator<MyEnum>() {
@Override
public MyEnum createFromParcel(final Parcel source) {
return MyEnum.values()[source.readInt()];
}
@Override
public MyEnum[] newArray(final int size) {
return new MyEnum[size];
}
};
}
그런 다음 Intent.put Extra(문자열, 구획 가능)를 사용할 수 있습니다.
업데이트: 레크커가 언급한 내용을 참고하시기 바랍니다.enum.values()
각 호출에 새 배열을 할당합니다.
템플릿이 .ParcelableEnum
이 솔루션을 구현합니다. (Windows의 경우 +J 사용)
열거형을 문자열로 전달할 수 있습니다.
public enum CountType {
ONE,
TWO,
THREE
}
private CountType count;
count = ONE;
String countString = count.name();
CountType countToo = CountType.valueOf(countString);
지정된 문자열이 지원되는 경우 열거형 값을 문제 없이 전달할 수 있습니다.
의도별로 열거형을 전달하는 경우 열거형을 정수로 변환할 수 있습니다.
예:
public enum Num{A ,B}
보내는 중( 열거형에서 정수로):
Num send = Num.A;
intent.putExtra("TEST", send.ordinal());
수신 중( 열거할 정수):
Num rev;
int temp = intent.getIntExtra("TEST", -1);
if(temp >= 0 && temp < Num.values().length)
rev = Num.values()[temp];
안부 전합니다.:)
에는 String을 할 수 .name()
그리고.valueOf(String)
다음과 같이:
class Example implements Parcelable {
public enum Foo { BAR, BAZ }
public Foo fooValue;
public void writeToParcel(Parcel dest, int flags) {
parcel.writeString(fooValue == null ? null : fooValue.name());
}
public static final Creator<Example> CREATOR = new Creator<Example>() {
public Example createFromParcel(Parcel source) {
Example e = new Example();
String s = source.readString();
if (s != null) e.fooValue = Foo.valueOf(s);
return e;
}
}
}
만약 당신의 열거형이 가변적인 상태를 가지고 있다면 이것은 분명히 작동하지 않습니다 (그들은 실제로 그러면 안 됩니다.
Enum을 Serializable로 구현한 다음 Intent를 통해 전달할 수 있습니다. 이를 Serializable로 전달하는 방법이 있기 때문입니다.열거형 대신 int를 사용하라는 충고는 거짓입니다.열거형은 코드를 읽기 쉽고 유지 관리하기 쉽게 만드는 데 사용됩니다.에넘을 사용할 수 없다는 것은 암흑 시대로 되돌아가는 큰 발걸음이 될 것입니다.
여기서 Parcelable 개념을 사용하는 답변은 대부분 Java 코드로 작성되어 있습니다.코틀린에서 하는 것이 더 쉽습니다.
@Parcelize 및 parcelable 인터페이스를 사용하여 열거형 클래스에 주석을 달기만 하면 됩니다.
@Parcelize
enum class ViewTypes : Parcelable {
TITLE, PRICES, COLORS, SIZES
}
Oderik의 게시물에 대해:
열거형을 구현할 수 있는 Parcelable을 만들 수 있습니다. 열거형은 매우 쉽습니다.
publicenum MyEnum에서 parcelable {}을(를) 구현합니다.Intent.putExtra(문자열, 구획 가능)를 사용할 수 있습니다.
MyEnum 변수 myEnum을 정의한 다음 intent.putExtra("Parcelable1", myEnum)를 수행하면 "MethodputExtra(String, Parcelable)가 유형 Intent에 대해 모호합니다." 오류 메시지가 표시됩니다.Intent.putExtra(String, Parcelable) 메서드도 있고 원래 'Enum' 유형 자체가 Serializable 인터페이스를 구현하기 때문에 컴파일러는 어떤 메서드(intent.putExtra(String, Parcelable/또는 Serializable)를 선택할지 알 수 없습니다.
MyEnum에서 Parcelable 인터페이스를 제거하고 다음과 같이 핵심 코드를 랩 클래스의 Parcelable 구현으로 이동하도록 제안합니다(Father2는 Parcelable이며 열거 필드 포함).
public class Father2 implements Parcelable {
AnotherEnum mAnotherEnum;
int mField;
public Father2(AnotherEnum myEnum, int field) {
mAnotherEnum = myEnum;
mField = field;
}
private Father2(Parcel in) {
mField = in.readInt();
mAnotherEnum = AnotherEnum.values()[in.readInt()];
}
public static final Parcelable.Creator<Father2> CREATOR = new Parcelable.Creator<Father2>() {
public Father2 createFromParcel(Parcel in) {
return new Father2(in);
}
@Override
public Father2[] newArray(int size) {
return new Father2[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mField);
dest.writeInt(mAnotherEnum.ordinal());
}
}
그러면 우리는 할 수 있습니다.
AnotherEnum anotherEnum = AnotherEnum.Z;
intent.putExtra("Serializable2", AnotherEnum.X);
intent.putExtra("Parcelable2", new Father2(AnotherEnum.X, 7));
enum에 enum 생성자를 사용하여 기본 데이터 유형을 가질 수 있습니다.
public enum DaysOfWeek {
MONDAY(1),
TUESDAY(2),
WEDNESDAY(3),
THURSDAY(4),
FRIDAY(5),
SATURDAY(6),
SUNDAY(7);
private int value;
private DaysOfWeek(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static final SparseArray<DaysOfWeek> map = new SparseArray<DaysOfWeek>();
static
{
for (DaysOfWeek daysOfWeek : DaysOfWeek.values())
map.put(daysOfWeek.value, daysOfWeek);
}
public static DaysOfWeek from(int value) {
return map.get(value);
}
}
를 사용하여 추가로 전달한 다음 값을 사용하여 열거에서 끌어낼 수 있습니다.
저는 심플한 게 좋아요.
- 프레드 활동에는 두 가지 모드가 있습니다.
HAPPY
그리고.SAD
. - 정적 만들기
IntentFactory
그것이 당신을 만듭니다.Intent
널 위해서.전달해 주세요Mode
너는 원한다. - 그
IntentFactory
의 이름을 사용합니다.Mode
추가 이름으로 클래스를 지정합니다. - 그
IntentFactory
변환합니다.Mode
아주String
사용.name()
- 에 들어갈 때
onCreate
이 정보를 사용하여 다시 a로 변환합니다.Mode
. 사용할 수 있습니다.
ordinal()
그리고.Mode.values()
뿐만 아니라.저는 디버거에서 문자열을 볼 수 있어서 좋아합니다.public class Fred extends Activity { public static enum Mode { HAPPY, SAD, ; } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.betting); Intent intent = getIntent(); Mode mode = Mode.valueOf(getIntent().getStringExtra(Mode.class.getName())); Toast.makeText(this, "mode="+mode.toString(), Toast.LENGTH_LONG).show(); } public static Intent IntentFactory(Context context, Mode mode){ Intent intent = new Intent(); intent.setClass(context,Fred.class); intent.putExtra(Mode.class.getName(),mode.name()); return intent; } }
이러한 목록을 문자열(또는 지도)과 같은 분류 가능한 것으로 변환하여 활동으로 가져오는 것이 최선의 방법이라고 생각합니다.그러면 활동에서 이를 다시 배열로 변환해야 합니다.
커스텀 parcelables를 구현하는 것은 IMHO의 골칫거리이기 때문에 가능하면 피하고 싶습니다.
다음 열거형을 고려합니다.
public static enum MyEnum {
ValueA,
ValueB
}
합격의 경우:
Intent mainIntent = new Intent(this,MyActivity.class);
mainIntent.putExtra("ENUM_CONST", MyEnum.ValueA);
this.startActivity(mainIntent);
의도/번들/인수에서 다시 검색하기:
MyEnum myEnum = (MyEnum) intent.getSerializableExtra("ENUM_CONST");
열거형만 보내고 싶다면 다음과 같은 작업을 수행할 수 있습니다.
먼저 일부 값(의도를 통해 전달될 수 있음)을 포함하는 열거형을 선언합니다.
public enum MyEnum {
ENUM_ZERO(0),
ENUM_ONE(1),
ENUM_TWO(2),
ENUM_THREE(3);
private int intValue;
MyEnum(int intValue) {
this.intValue = intValue;
}
public int getIntValue() {
return intValue;
}
public static MyEnum getEnumByValue(int intValue) {
switch (intValue) {
case 0:
return ENUM_ZERO;
case 1:
return ENUM_ONE;
case 2:
return ENUM_TWO;
case 3:
return ENUM_THREE;
default:
return null;
}
}
}
그러면:
intent.putExtra("EnumValue", MyEnum.ENUM_THREE.getIntValue());
그리고 당신이 그것을 얻고 싶을 때:
NotificationController.MyEnum myEnum = NotificationController.MyEnum.getEnumByValue(intent.getIntExtra("EnumValue",-1);
식은 죽 먹기!
Kotlin 확장 함수 사용
inline fun <reified T : Enum<T>> Intent.putExtra(enumVal: T, key: String? = T::class.qualifiedName): Intent =
putExtra(key, enumVal.ordinal)
inline fun <reified T: Enum<T>> Intent.getEnumExtra(key: String? = T::class.qualifiedName): T? =
getIntExtra(key, -1)
.takeUnless { it == -1 }
?.let { T::class.java.enumConstants[it] }
이렇게 하면 동일한 열거형을 여러 개 전달하거나 기본적으로 클래스 이름을 사용할 수 있습니다.
// Add to gradle
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
// Import the extension functions
import path.to.my.kotlin.script.putExtra
import path.to.my.kotlin.script.getEnumExtra
// To Send
intent.putExtra(MyEnumClass.VALUE)
// To Receive
val result = intent.getEnumExtra<MyEnumClass>()
열거형 사용 안 함.번호를 사용하지 않는 이유 #78.:) Bundle 및 Parcelable을 통해 쉽게 원격으로 이동할 수 있는 정수를 사용합니다.
언급URL : https://stackoverflow.com/questions/2836256/passing-enum-or-object-through-an-intent-the-best-solution
'programing' 카테고리의 다른 글
Oracle에서 문자 집합 불일치 오류 (0) | 2023.07.25 |
---|---|
대규모 데이터셋을 위한 데이터베이스 설계 (0) | 2023.07.25 |
오류로 인한 Gulp Watch 깨짐 (0) | 2023.07.25 |
매우 큰 테이블에서 Mysql 개수 성능 (0) | 2023.07.25 |
팬더 뱃놀이는 경기력에 문제가 있습니까? (0) | 2023.07.25 |