Android: передача хэш-карты между действиями - PullRequest
18 голосов
/ 06 апреля 2011

У меня есть карта между строкой и объектом класса.Я заполняю эту карту в Activity1, и я хотел бы передать ее в Activity2.

public class NEW extends Activity {

    public class data {
            String name;
            float value;
                 ....   etc  }

 ......   
    static Map<String, data> data_map = new HashMap<String, data>();
   .....  }

Ответы [ 5 ]

53 голосов
/ 06 апреля 2011

Лучший способ сделать это, если вы можете выразить свои данные в примитивах, поддерживаемых 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);
        }
    }
}

Обратите внимание, что когда у вас есть пользовательская структура данных, например, ваш класс «data», может быть проще сделать этоParcellable, поэтому он знает, как читать / записывать свое содержимое в Parcel, и код здесь будет просто вызывать .writeToParcel (...) и метод .readFromParcel (...), а не знать подробности его содержимого.,Таким образом, когда вы добавляете новые поля в «data», вы не забываете также обновить этот другой код сортировки, чтобы узнать о них.

22 голосов
/ 06 апреля 2011

Я предполагаю, что вы владеете обоими видами деятельности (назовите их A и B).В этом случае просто поместите карту в общедоступную статическую переменную и получите доступ к ней из B через A.data_map.

[update]

Для всех отрицательных голосов возьмитезагляните в раздел FAQ по Android Application Framework «Как передавать данные между операциями / службами в рамках одного приложения?».Решение, которое я рекомендую, точно такое же, как ...

Публичное статическое поле / метод

Альтернативный способ сделать данные доступными через деятельность / службы использовать открытые статические поля и / или методы.Вы можете получить доступ к этим статическим полям из любого другого класса в вашем приложении.Для совместного использования объекта действие, которое создает ваш объект, устанавливает статическое поле для указания на этот объект, а любое другое действие, которое хочет использовать этот объект, просто получает доступ к этому статическому полю.

Да, есть предостереженияк этому решению, но с ограниченной информацией, представленной OP, мы не можем предполагать, что этот метод не будет работать.

5 голосов
/ 06 апреля 2011

Я бы предложил использовать 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.

Если вам нужны дополнительные разъяснения, добавьте комментарий.

0 голосов
/ 03 мая 2012

Создайте новый 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;
}

Эти шаги могут быть полезны для вас ...

0 голосов
/ 03 мая 2012

Вы можете инкапсулировать свои данные в Связанной службе, как описано в этом документе:

http://developer.android.com/guide/topics/fundamentals/bound-services.html

Не забудьте добавить свой сервер в файл манифеста.

это решение имеет то преимущество, что отделяет ваши данные от вашего пользовательского интерфейса, что в конечном итоге приведет к более удобному дизайну.

Если возникнет необходимость, вы можете добавить оболочку обмена сообщениями в API вашего сервиса, чтобы позволитьвызывается из других процессов / приложений

...