Zentrales XML-Model

  • Hallo zusammen,


    ich hätt´ da mal wieder ein Problem: Es erweitert im grunde einer meiner früheren Fragen, die ich zum Glück als gelöst betrachte. Es geht dabei um eine grundlegende Frage zur Struktur meiner App:


    Ausgangssituation 1:
    - Was will ich können: Ich parse aus meiner main-Activity mit einem DocumentBuilder aus javax.xml.parsers ein XML-Dokument. Ob ich dieses außerhalb der Activity noch brauche, weiß ich noch nicht ganz genau. Ich habe das Ganze jetzt außerdem in einen AsyncTask ausgelagert, der mir nach Ende des Parsens das Attribut setzt, also in Kurzform:



    Frage 1:
    Ist das so soweit erstmal sinnig, also insbesondere "doc" als Attribut anzulegen und dann direkt "aus der Activity heraus" zu parsen? Oder sollte man diese ganze Funktionalität irgendwie in einer weiteren Klasse "kapseln"?


    Frage 2:
    Gesetzt den Fall, ich würde dieses doc nun auch in anderen Activities verwenden wollen (und z.B. auch ändern wollen), wie übergebe ich es dann sinnvollerweise an andere Activities? Ich habe an dieser Stelle einiges über das Singleton-Entwurfsmuster gelesen, aber das wird ja gern auch als versteckte globale Variable verpönt. Also: Letzten Endes sind die Daten des docs gemäß einer Aufteilung in Model-View-Controller ja der Model-Schicht zuzuordnen, wie baue ich mir aber diese Model-Schicht sinnvollerweise am besten auf? Insbesondere könnte ja meine main-Activity nicht die einzige sein, die daran interessiert ist, ob z.B. das Parsen beendet ist?!


    EDIT Frage 3:
    Die letzte Frage ergänzend: Wieviel "Logik" was das Aufbauen irgendwelcher Verbindungen, das Parsen einer xml, ... angeht sollte denn die Activity überhaupt beinhalten?


    Erneut leicht verwirrte Grüße,
    FargoTof

  • Zitat

    Frage 1:


    Ist das so soweit erstmal sinnig, also insbesondere "doc" als Attribut
    anzulegen und dann direkt "aus der Activity heraus" zu parsen? Oder
    sollte man diese ganze Funktionalität irgendwie in einer weiteren Klasse
    "kapseln"?

    Activities enthalten Anwendungslogik, da kannst du das schon so machen. Wenn du diese Funktionaliät noch an anderer Stelle in deiner App brauchst, würde ich das aber immer in eine eigene Klasse kapseln, alleine schon wg der Übersichtlichkeit.



    Zitat

    Frage 2:


    Gesetzt den Fall, ich würde dieses doc nun auch in anderen Activities
    verwenden wollen (und z.B. auch ändern wollen), wie übergebe ich es dann
    sinnvollerweise an andere Activities?

    Dann schreib dein doc in eine Klasse, verpasse ihr die Möglichkeit Serializable zu sein und dann halt per putextra / getextra wie gehabt an andere Activities übergeben. (Komplexe Datentypen müssen dieses Interface besitzen.)



    Zitat

    EDIT Frage 3:


    Die letzte Frage ergänzend: Wieviel "Logik" was das Aufbauen
    irgendwelcher Verbindungen, das Parsen einer xml, ... angeht sollte denn
    die Activity überhaupt beinhalten?

    Siehe Frage1, das musst du selbst abschätzen wie und wo du doc noch einsetzen möchtest - wenn du es in eine Klasse kapselst hast du halt eine saubere Schnittstelle und gut ist. Du kannst Sie in deinem nächsten Projekt wiederverwenden.

  • Dann schreib dein doc in eine Klasse, verpasse ihr die Möglichkeit Serializable zu sein und dann halt per putextra / getextra wie gehabt an andere Activities übergeben. (Komplexe Datentypen müssen dieses Interface besitzen.)


    hmm... ist es nicht aber so, dass per putextra beim serialisieren / deserialisieren eine neue Instanz erzeugt wird? Sodass ich nach Änderungen an den Daten beim zurückschalten auf die erste Activity diese wieder extra übergeben muss? Von anderen Programmiersprachen (zuletzt Objektive-C für iOS) bin ich es zB gewohnt, einem neuen ViewController (was ja IN ETWA einer Activity entspricht), einfach eine Referenz auf das entsprechende Objekt zu übergeben..


    Aber generell tue ich mich leider etwas schwer, die einzelnen Funktionen sinnvoll auf Klassen aufzuteilen, MVC und andere Entwurfsmuster hin oder her: In der Theorie klingts immer alles super logisch, in der Praxis trennt sichs schon deutlich schwerer... Gibts denn hierfür irgendwelche allgemeinen Tips?


    Grüße,
    FargoTof

  • Leider sind die Activities bei Android relativ unabhängig und die Speicherverwaltung kann einem da auch noch mal einen Strich durch die Rechnung machen.


    Wenn du die Daten konsistent halten willst, dann am besten in die SQLiteDB reinstecken, die Activities sollten sich dann in onResume mit den aktuellen Daten versorgen. Bei kleinen Datenmengen kannst du auch die Prefs als Speicher benutzen - man muss ja keine Konfiguration für diese Daten einbauen. Man kann auch die serialisierte Form eines Documents in ein DB-Feld speichern - die Daten sind dann auch bei Stromausfall/Abbruch der App noch im letzten Zustand - ein Vorteil gegenüber reiner Hauptspeichernutzung.


    Das hat zusätzlich den Vorteil, dass du schon mal Daten hast, auch wenn noch nix aus dem Internet angekommen ist.


    Ob du die Daten in einer Document-Struktur hältst oder lieber eine eigene Struktur aufbaust, ist eher Geschmackssache - kommt auch drauf an, ob du die Daten im XML-Format wieder rausgeben möchtest - da ist Document klar im Vorteil. Nur die Zugriffe in den Baum sind ziemlich nervig, wenn man einzelne Werte braucht.


    @kilphil: du warst schon wieder schneller... *g*

  • Du musst doch die Daten sowieso wieder übergeben, unter Android kannst du doch nie wissen ob er die Activity schon aus dem Speicher gehauen hat, weil er Platz brauchte.



    Hmmm, das ist natürlich ein berechtigter Einwand... Allerdings gibt es abgesehen von globalen Variablen wirklich keine Möglichkeit, Daten (ein Model) zu halten, auf die verschiedene Objekte zu verschiedenen Zeiten gleichberechtigt zugreifen können?


    Ich meine das ist ja kein ungewöhnlicher Ansatz, zB einmal Daten zu laden und diese dann auf unterschiedliche Arten (also aus unterschiedlichen Activities) zu bearbeiten..


    FargoTof

  • Das hat zusätzlich den Vorteil, dass du schon mal Daten hast, auch wenn noch nix aus dem Internet angekommen ist.


    Ob du die Daten in einer Document-Struktur hältst oder lieber eine eigene Struktur aufbaust, ist eher Geschmackssache - kommt auch drauf an, ob du die Daten im XML-Format wieder rausgeben möchtest - da ist Document klar im Vorteil. Nur die Zugriffe in den Baum sind ziemlich nervig, wenn man einzelne Werte braucht.



    Hmm, naja, die App wird in einem lokalen Netzwerk mit einer bestehenden Hardware zusammenarbeiten, quasi ein Art Fernbedienung, die "offline" ohnehin keinen Sinn ergibt. Und: Die Daten sollen auch wieder als xml-rausgeschrieben werden - Es ist quasi:


    Aktuelle Einstellungen vom Server laden
    Aktuelle Einstellungen bearbeiten (und dabei "live" anwenden)
    Aktuelle Einstellungen wieder abspeichern


    Von daher muss ich eigentlich nichts persistent auf dem Gerät speichern (zumal die Einstellungen auf dem Server auch von einem zweiten Device aus geändert werden können).

  • Intents werden manchmal auch aus anderen Gründen gepackt, z.B. um Daten wieder zurück zu geben, um Services zu starten oder Anfragen ans System (ok, auch Services).


    Ich hab sie am Anfang auch etwas unhandlich gefunden, aber mittlerweile hab ich mich dran gewöhnt.

  • Achtung OT


    Grundsätzlich richtig, aber was passiert nach dem Verschicken ???


    Er versucht den Intent an den Mann zu bringen und das führt z.b. zum Erschaffen einer Activity.

    Code
    Intent web = new Intent(Intent.ACTION_VIEW, Uri.parse(targeturl));
    
    
    				  startActivity(web);




    Startet ja den Webbrowser, was ja letztendlich auch bloss eine Activity ist.


    ENDE OT




    Der Threadersteller möchte aber eine Instanz seines XML Dokuments / Klasse in der App erstellen und von allen möglichen Activies Zugriff auf dieses Objekt/Klasse haben, ohne sie ständig hin un her zu schubsen, wie gesagt klingt im Ansatz nach einer superglobalen Variable.

  • hmm, nagut, ich sehe es ja schon ein.. :) Vllt ist mein Problem auch einfach, dass mir globale Variablen/Singletons immer ein Stück weit als Behelfslösung vorkamen, aber wenn a) es ein "common Java way" ist und b) der bei Stackoverflow genannte Weg über die Einbindung in den App-Context ja noch ein Stück "sauberer" erscheint, nehme ich das vllt einfach mal so hin :)


    Trotzdem mal anders gefragt: Haltet ihr eure Daten / eurer Model auch so, oder habt ihr intelligentere Klassendesigns gefunden, die dieses Problem i.d.R gar nicht erst aufkommen lassen?


    Grüße!

  • Hallo zusammen,


    ergänzend zur ursprünglichen Frage (ist alles halbwegs umgesetzt, superglobale Variable funktioniert soweit) hat sich mittlerweile eine neue Fragestellung ergeben: In meinem zentralen "Model" führe ich alle Dinge durch, die ggf. für mehrere Activities von Belang sein könnten. Dazu gehört nun u.a. auch das "Deserialisieren" verschiedener XML-Files (auf einem externen Server) mithilfe des SimpleXML-Frameworks in einem AsyncTask.


    Problematisch ist, dass es sich um eine recht große Menge an Daten handelt, im entscheidenden Fall um eine Sammlung 200 verschiedener Varianten eines Datensatzes von je etwa 1000 Zeilen Länge. Da das den Memory schnell überlaufen lässt, habe ich mich entschlossen, das Ganze auf Setting000.xml bis Setting200.xml aufzuteilen, die ich dann gern jeweils nach Bedarf laden würde.


    Stellt sich die Frage nach einem vernünftigen Callback-Mechanismus, über den die Activities jeweils ein konkretes Setting "anfordern" könnten: Für eine einzelne Datei wäre das ja noch recht übersichltich zu handeln, aber auch aktuell kamen bereits noch verschiendene andere XML-Files hinzu, sodass alle ModelListener ein mehrere Methoden umfassendes Interface implementieren mussten; im Wesentlichen konnte ich mich aber darauf beschränken, mitzuteilen, wenn eine Datei deserialisiert wurde, also die Daten verfügbar waren.


    Jetzt müsste ich nach meiner Vorstellung aus der Activity dem AsyncTask des Models die Anfrage nach z.B. Setting100 übergeben, das Ergebnis würde dann an alle Listeners, also zB. meine Activity, übergeben. Nun käme dort eine doch recht fehleranfällige Prüfung, ob ich diese Daten überhaupt brauche (zB. ob ich sie überhaupt selber angefordert habe, ...)


    Alles in allem erstmal irgendwie nicht sonderlich übersichtlich und ich frage mich, wie man das geschickter lösen könnte..?! Ich hoffe mein Problem verständlich dargestellt zu haben und freue mich auf eure Vorschläge,


    Viele Grüße,
    FargoTof

  • Hmm, also so richtig klar geworden ist mir dein Problem nicht und eventl liest das hier auch sonst keiner, weil es üblich ist, bei einem neuen Problem einen neuen Thread aufzumachen....



    Ich habe das Gefühl das du dein Android Handy mit einem vollwertigen Desktoprechner verwechselst. Wenn du schon vorher weisst das 200 XML Dateien geladen werden sollte man über seine Implementierung nachdenken. Es ist ja von Hause aus bekannt, das Androidhandys oft eine gewisse Limitierung beim Arbeitsspeicher haben.


    -> SQLLite-Datenbanken sind vielleicht eine gute Möglichkeit deine XML Daten zu cachen bzw. in ein "Android" freundlicheres Format um zu wandeln und den Zugriff transparenter zu gestalten. So könntest du Dir auch einen Contentprovider schaffen, welcher die ganze Logik der Datenanforderung enthält.


    In jeder Activity die angeforderten Daten zu überprüfen zeugt in meinen Augen auch von einem schlechten Ansatz, klingt schlimm nach redundatem Code.


    Naja aber vielleicht erklärst du noch mal genauer, was du vorhast dann bekommt man vielleicht eine Ahnung davon, in welche Richtung du steuerst.

  • Okay, ich hatte schon befürchtet, dass es schwer verständlich ein könnte ;)


    Also: Es geht im Prinzip um eine Art Hausautomation, bei der eine große Anzahl (ca. 100) an RGB-Leuchten 1. einzeln eingestellt werden können soll, 2. diese einzelnen Einstellungen zu Gesamteinstellungen zusammengefasst werden sollen und 3. verschiedene Inszenierungen abgespielt werden können.


    Insbesondere letztere sind es, die mir Sorge bereiten:
    Eine Insznierung besteht dann aus X (ca. 20) Schritten, in der für alle 100 Lichtquellen die zugehörige Einzeleinstellung gespecihert werden muss, also in etwa so:



    Macht also bereits für eine einzige Insznierung ne Menge Daten... Problem ist jetzt also, dass ich das Laden dieser xml (von einem Server) gern ins Model verlagern würde (asynchron muss es ja eh laufen), und gleichzeitig eine Visualisierung in verschiedenen Activities brauche, beispielsweise eine "tabellarische" Ansicht der Inszenierung, ... Und genau da weiß ich eben nicht, wie ich am besten vorgehe: Alle Daten auf einmal laden geht halt mangels Speicher nicht. Also müsste ich irgendwie vom Model "SequenceXY" anfordern können und bräuchte in meiner Activity die entsprechenden Methoden, die das Model nach dem Laden dann zur Übergabe der Daten aufrufen könnte. Nur stellt sich das in meinem Kopf grade recht unübersichtlich und kompliziert dar... :(


    Hast du da eine bessere Idee? (Bestimmt hast du die ;)!)


    PS: XML auf dem zentralen Server wäre grundsätzlich schon das Mittel meiner Wahl, da man da bei Bedarf auch mal "von Hand" ändern könnte.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!