Android: передача хэш-карты между действиями
У меня есть карта между строкой и объектом класса. Я заполняю эту карту в Activity1, и я хотел бы передать ее активности2.
public class NEW extends Activity {
public class data {
String name;
float value;
.... etc }
......
static Map<String, data> data_map = new HashMap<String, data>();
..... }
Ответы
Ответ 1
Я предполагаю, что у вас есть обе виды деятельности (назовите их A и B). В этом случае просто поместите карту в общедоступную статическую переменную и получите доступ к ней из B через A.data_map.
[обновление]
Для всех downvotes загляните в Часто задаваемые вопросы о платформе Android: "Как передавать данные между Activity/Services в одном выражение?". Решение, которое я рекомендую, точно такое же, как...
Публичное статическое поле/метод
Альтернативный способ сделать данные доступный для всех видов деятельности/услуг является использовать общедоступные статические поля и/или методы. Вы можете получить доступ к этим статическим полей из любого другого класса в вашем выражение. Чтобы поделиться объектом, активность, которая создает ваш объект устанавливает статическое поле, указывающее на это объекта и любой другой деятельности, которая хочет использовать этот объект только для доступа это статическое поле.
Да, есть предостережения для этого решения, но с ограниченной информацией, представленной OP, мы не можем предположить, что этот метод не будет работать.
Ответ 2
Лучший способ сделать это - вы можете выразить свои данные в примитивах, поддерживаемых Bundle, поэтому его можно поместить в намерение, которое вы отправляете с помощью методов Intent.putExtra(). (ЗА ИСКЛЮЧЕНИЕМ для использования Serializable, который чрезвычайно медленный и неэффективный.)
Однако вы не можете этого сделать, потому что (a) вы используете карту и (b) ваша карта содержит пользовательский тип данных.
Формально правильное решение этой точной проблемы состоит в том, чтобы написать собственный класс Parcellable, который заботится о сортировке/разборке вашей структуры данных. Я нарисую код здесь, хотя это может быть и не совсем правильно:
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
public class MyData implements Parcelable {
HashMap<String, data> data_map = new HashMap<String, data>();
public MyData() {
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int parcelableFlags) {
final int N = data_map.size();
dest.writeInt(N);
if (N > 0) {
for (Map.Entry<String, data> entry : data_map.entrySet()) {
dest.writeString(entry.getKey());
data dat = entry.getValue();
dest.writeString(dat.name);
dest.writeFloat(dat.value);
// etc...
}
}
}
public static final Creator<MyData> CREATOR = new Creator<MyData>() {
public MyData createFromParcel(Parcel source) {
return new MyData(source);
}
public MyData[] newArray(int size) {
return new MyData[size];
}
};
private MyData(Parcel source) {
final int N = source.readInt();
for (int i=0; i<N; i++) {
String key = source.readString();
data dat = new data();
dat.name = source.readString();
dat.value = source.readFloat();
// etc...
data_map.put(key, dat);
}
}
}
Обратите внимание, что когда у вас есть настраиваемая структура данных, например, ваш класс данных, она может быть более чистой, чтобы также сделать эту Parcellable, поэтому она знает, как читать/писать ее содержимое на посылке, а код здесь просто вызовет .writeToParcel(...) и метод .readFromParcel(...), вместо того, чтобы знать подробности его содержимого. Таким образом, когда вы добавляете новые поля в "данные", вы не забываете также обновлять этот другой код маршаллинга, чтобы узнать о них.
Ответ 3
Я бы предложил использовать Intents, которые работают как для статических, так и для арбитальных объектов (если они реализуют Serializable). Создайте Intent для своего приложения, а затем передайте свой HashMap (а не карту, которая не реализует Serializable!) В качестве дополнительных данных
Intent act2 = new Intent(Activity2.SHOW_ME);
act2.putExtra("data", data_map);
Затем в Activity2 вы можете вызвать getIntent()
и проверить через Intent.getAction().equals(Activity2.SHOW_ME)
, был ли вы тем, кто вызвал вашу активность. Если это так, вы можете получить доступ к своим дополнительным данным с помощью
Intent caller = getIntent();
if (caller.getAction().equals(Activity2.SHOW_ME)) {
Map<String, NEW.data> data_map = (Map<String, NEW.data>)caller.getExtras().get("data");
}
Надеюсь, я все правильно набрал;) Это предполагает, что ваша строка действия Intent хранится как static final string SHOW_ME = "yourpackage.yourname";
в Activity2.
Если вам нужно уточнить, добавьте комментарий.
Ответ 4
Вы можете инкапсулировать свои данные в Bound Service, как описано в этом документе:
http://developer.android.com/guide/topics/fundamentals/bound-services.html
Не забудьте добавить свой сервер в файл манифеста.
Это решение имеет то преимущество, что вы отключите свои данные от вашего пользовательского интерфейса, что в конечном итоге приведет к более удобному дизайну.
Если возникнет такая необходимость, вы можете добавить оболочку обмена сообщениями в свой API-интерфейс службы, чтобы он мог быть вызван из других процессов/приложений
Ответ 5
Создайте новый Java файл, который будет глобальным для всего приложения.
Step1
public class GlobalClass extends android.app.Application
{
public static Map<String, NEW.data> data_map = new Map<String, NEW.data>();
}
Step2
После этого зарегистрируйте этот "GlobalClass" в AndroidManifest.xml
<application
android:name=".GlobalClass"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
</application>
Step3
теперь вы можете использовать эту карту в любом месте своего приложения.
@Override
protected void onCreate(Bundle icicle)
{
GlobalClass global = (GlobalClass)getApplication();
Map<String, NEW.data> my_map_data = global.data_map;
}
Эти шаги могут быть полезны для вас...