Intent.putExtras mit komplexen Objekten?

  • Antworten:7
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 105

01.04.2010 09:20:49 via Website

Guten morgen,

ich hab da 2 Activities (A1 und A2).

In A1 wird XML geladen und geparst und die Daten angezeigt.

Will nun der Benutzer A2 betrachten, so würde ich gerne per Intent den Teil der Objekte (aus dem XML geparst) durchreichen.

Leider finde ich bei Intent.putExtras nichts für Object.

Alles auf String runterzubrechen ist etwas aufwendig (wären ca 180 Strings).

Wie ist das bei Android angedacht?

Mein Plan B wäre übrigens die oberste Datenklasse als Singleton zu implementieren...

Viele Grüße
Marco

PS: langes Wochenende in Sicht :)

Antworten
  • Forum-Beiträge: 105

01.04.2010 09:56:32 via Website

ich denke hiermit sollte es gehen:

Intent.putExtra(String, Parcelable)

Intent.putExtra(String, Serializable)

In meiner Thesis über Android hab ich die Erfahrung gemacht dass Objektserialisierung und -deserialisierung extrem langsam ist unter Android :(

Parcelable ist komplett neu für mich.

Das Hauptobjekt was ich durchreichen möchte ist Response4Bundesliga, welches einige andere Klassen referenziert (liegt an meinem XML Model):

1public class Response4Bundesliga {
2 public Results results;
3}
4
5public class Results {
6 public String day;
7 public List<Result> listResult = new ArrayList<Result>();
8}
9
10public class Result {
11 public String index;
12 public Home home;
13 public Guest guest;
14 public String finalResult;
15 public String halftimeResult;
16}
17
18public class Home {
19 public String name;
20 public String icon;
21}
22
23public class Guest {
24 public String name;
25 public String icon;
26}

Gruß
Marco

Antworten
  • Forum-Beiträge: 1.727

01.04.2010 10:59:44 via Website

Ein Parcleable sieht z.b so aus:

1public class AlarmDetail implements Parcelable
2{
3 private final int alarmID;
4
5 private final String name;
6
7 private final String stationID;
8
9 public AlarmDetail(final int _alarmID, final String _stationID, final String _name)
10 {
11 alarmID = _alarmID;
12 stationID = _stationID;
13 name = _name;
14 }
15
16 private AlarmDetail(final Parcel _parcel)
17 {
18 alarmID = _parcel.readInt();
19 name = _parcel.readString();
20 stationID = _parcel.readString();
21 }
22
23 /**
24 * Returns the Alarm ID
25 *
26 * @return
27 */
28 public int getId()
29 {
30 return alarmID;
31 }
32
33 /**
34 * @return the name
35 */
36 public String getName()
37 {
38 return name;
39 }
40
41 /**
42 * @return the station id
43 */
44 public String getStationID()
45 {
46 return name;
47 }
48
49 /*
50 * (non-Javadoc)
51 *
52 * @see android.os.Parcelable#describeContents()
53 */
54 @Override
55 public int describeContents()
56 {
57 return 0;
58 }
59
60 /*
61 * (non-Javadoc)
62 *
63 * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
64 */
65 public void writeToParcel(final Parcel out, final int flags)
66 {
67 out.writeInt(alarmID);
68 out.writeString(name);
69 out.writeString(stationID);
70 }
71
72 /**
73 * @see Creator
74 */
75 public static final Parcelable.Creator<AlarmDetail> CREATOR = new Parcelable.Creator<AlarmDetail>()
76 {
77 public AlarmDetail createFromParcel(final Parcel in)
78 {
79 return new AlarmDetail(in);
80 }
81
82 public AlarmDetail[] newArray(final int size)
83 {
84 return new AlarmDetail[size];
85 }
86 };
87}


Singletons machen das ganze mehr als unflexibel und sind schlecht zu testen.

Echte Serialisierung ist unter Android wohl wirklich overkill.


hth,
Mac

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
  • Forum-Beiträge: 105

02.04.2010 11:51:21 via Website

also das mit den Parcelable klappt eigentlich ganz gut.

primitive typen wie string oder integer sind mal gar kein problem.

typisierte listen finde ich nicht so schön.

folgendes:

1public class Table implements Parcelable {
2
3 public List<Row> listRow = new ArrayList<Row>();
4
5 ....
6
7 @Override
8 public void writeToParcel(Parcel dest, int flags) {
9 dest.writeList(listRow);
10 }
11
12 public void readFromParcel(Parcel in) {
13 in.readList(listRow, null);
14 }
15}

dieser teil zumindest funktioniert nicht.

Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: Row

Nachdem ich etwas gegoogelt habe, hab ich diese Lösung gefunden.

1@Override
2 public void writeToParcel(Parcel dest, int flags) {
3 dest.writeInt(listRow.size());
4 for( int i=0; i<listRow.size(); i++ ) {
5 listRow.get(i).writeToParcel(dest, flags);
6 }
7 }
8
9 public void readFromParcel(Parcel in) {
10 int size = in.readInt();
11 for( int i=0; i<size; i++ ) {
12 listRow.add(new Row(in));
13 }
14 }

Finde ich etwas zu händisch. Kann ja nicht sein dass ich sowas per Hand machen muss, da ich wohl Methoden angeboten bekomme für ne List.

Hat jemand ne Lösung?

Gruß
Marco

PS: frohe Ostern :)

Antworten
  • Forum-Beiträge: 1.727

02.04.2010 12:08:02 via Website

Nö, ich finde diese Lösung gut, sie ist schlank! In einem Desktop Projekt wo es ebenfalls auf Speed ankam haben wir das ebenfalls so gelöst.
Schlimm wäre es wohl wenn du an zig stellen so etwas benötigst ? Aber selbst dann wäre der Code doch weiterhin in den Parcelable gekapselt.

ClassNotFoundException when unmarshalling: Row

Das wundert mich, ist die Klasse wirklich dort bekannt wo sie sein sollte ? Ist es ein Parcelable ?

- Mac

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
  • Forum-Beiträge: 105

02.04.2010 12:13:45 via Website

hi,

genau so ist es.

row ist selber ein parcelable mit komplexen objekten und strings, wobei die komplexen objekte wiederum selber parcelable sind.

habs der reihe nach aufgebaut, also erst die klasse team (mit strings), dann die klasse row (mit team und strings), und zuletzt table (mit liste von teams).

die kapselung hat sich so ergeben, weil ich ein fertig xml so am besten unmarshalle (mit xstream).

gruß
marco

ps: ich vermute ja, dass die liste nur aus primitiven typen wie string, integer usw bestehen darf, und nicht aus row, daher kennt er es nicht...

Antworten
  • Forum-Beiträge: 1.727

03.04.2010 12:22:09 via Website

Du könntest aber auch einfach eine ID übermitteln und das ganze in eine SQLite DB persistieren!

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten