Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

XoR

Frischling

  • »XoR« ist der Autor dieses Themas
  • Private Nachricht senden

1

05.09.2012, 04:13

[Android] FrameLayout speichern?

Hi zusammen.

Dieses Thema hat eigentlich nichts mit Spielen zu tun, dennoch hoffe ich, dass mir wer weiterhelfen kann. Ich habe auch auf Android-Plattformen um Hilfe gebeten, doch da es dort erfahrungsgemäß sehr lange dauert bis man eine Antwort erhält die zudem noch nützlich ist und ich sehr positive Erfahrung mit dieser Plattform hatte, bitte ich hier ebenfalls um Hilfe :-)


Doch nun zum Eigentlichen:

Ich habe einen ViewFlipper der zwischen verschiedenen Views hin- und herflippt. Durch Einstellungen kann man bestimmte Views "ausschalten" (removeView(View Child)) sodass dieses fortan nicht mehr angezeigt wird und nur noch zwischen den übrigen Views wechselt.Da ich aber diese Einstellung auch wieder rückgängig machen kann/will (View soll fortan wieder angezeit werden) muss ich es wieder als Child vom ViewFlipper setzen
(addView(View Child)), was auch funktioniert, wenn man die App nicht neu startet.
Wenn ich nun aber ein View (nennen wir es Child2) ausschalte, die App anschließend neu starte und dann in den Einstellungen einstelle, dass Child2 fortan wieder angezeigt werden soll, stürzt die App ab.

Meine Vermutung war, dass Child2 nach dem Neustart erst gar nicht neu geladen wird, und ich es somit auch nicht wieder dem ViewFlipper als Child zuweisen kann.Deshalb dachte ich mir, dass ich diese ganzen Views beim ersten mal starten der App im SharedPreferences speicher, um sie somit immer wieder laden und dem ViewFlipper als Child zuweisen kann. Durch Google bin ich auf diese Seite gestoßen: eigene Objekte Speichern

Habe diese Methoden für FrameLayouts angepasst (meine zu wechselnde Views sind FrameLayouts):

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//#####################################################################
    // SERIALISIERUNG #####################################################
    //#####################################################################
    
    public static String objectToString(Object obj) {
        
        String out = null;
        
        if (obj != null) {
            
            try {
                
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                
                oos.writeObject(obj);
                
                out = new String(Base64Coder.encode(baos.toByteArray()));
                
            } catch (IOException e) {
                
                return null;
            }
        }
        return out;
    }
     
    
    public static Object stringToObject(String str) {
        
        Object out = null;
        
        if (str != null) {
            
            try {
                
                ByteArrayInputStream bios = new ByteArrayInputStream(Base64Coder.decode(str));
                ObjectInputStream ois = new ObjectInputStream(bios);
                
                out = ois.readObject();
                
            } catch (IOException e) {
                
                return null;
                
            }catch (ClassNotFoundException e) {
                
                return null;
            }
        }
        return out;
    }
    
    
    public boolean storeMyData(FrameLayout myDataObject, String Dataname ) {
        
        try {
            
            String s = objectToString(myDataObject);
            
            if(s != null && s.length() > 0) {
                
                    memoryEdit.putString(Dataname, s);
                    memoryEdit.commit();
                    
                    return true;
            }
            
            return false;
            
        }catch (Exception e) {
            
            return false;
        }
    }
    
    
    
    public FrameLayout loadMyData(String Dataname) {
        
        if(memory.contains(Dataname)) {
            
            String s =  memory.getString(Dataname, "");
            
            if(s.length() > 0) {
                
                try {
                    
                    return (FrameLayout) stringToObject(s);
                }
                
                catch (Exception e) {
                    
                    return null;
                }
            }
        }
        return null;
    }


Dies hat - wie erwartet - nicht funktioniert, vermute zum Teil, da ich nicht in die Klassendefinition vom FrameLayout gekommen bin (vll. bin ich zu dumm) und es somit nicht implements Serializable machen konnte.


Ich Hoffe ihr hab eine Lösung, wie ich diese Views beim ersten mal ausführen der App speichern kann, oder bin ich mit meiner Vermutung total auf dem Holzweg?

Sorry wegen dem vielen Text :-D



MfG XoR

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

2

05.09.2012, 08:14

ich kann nicht ganz nachvollziehen, warum du die Views speichern willst
wenn du das Programm startest, dann werden die Views erzeugt, richtig?
was würde dagegen sprechen, dies bei jedem Programmstart zu machen?
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

05.09.2012, 08:31

Is mir irgendwie auch nicht ganz klar. Man speichert üblicherweise ja den Zustand eines Programms und dessen Views, erzeugt beim Start aber generell erst mal alle, als ob es der erste Start wäre und stellt dann die Zustände wieder her.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

XoR

Frischling

  • »XoR« ist der Autor dieses Themas
  • Private Nachricht senden

4

05.09.2012, 14:30

Nach langem rumprobieren habe ich nun rausgefunden, dass das Problem keineswegs bei den FrameLayouts liegt, sondern anscheinend am Rückgabewert der Activity.
Zur besseren Verständlichkeit:

Meine MainActivity ruft durch Klick auf den "EinstellungsButton" eine Neue Activity (Settings) auf, in der man wie oben bereits erklärt bestimmte Views aus- und einschalten kann(mit Hilfe von Checkboxen).
Die werte der Checkboxen werden dann gespeichert, ein Rückgabewert wird ausgegeben und die Activity mit finish() beendet.
Nun fängt die MainActivity den Rückgabewert ab, und lädt die Views neu.
Dies funktioniert nur solange ich Views ausschalte, doch wenn ich eines wieder einschalten will stürtzt die App ab. Erwähnenswert ist noch, dass ich mittels AlertDialoge getestet habe, wie weit denn die App kommt bevor sie abbricht. dies ist (nur beim erneuten aktivieren eines Views) Zeile 50(in Settings). Somit denke ich, dass der Fehler in der Methode von MainActivity liegt (Zeile. 59), welche die RückgabeWerte abfängt/bearbeidet.

Hier noch mein Code:


CodeSchnippsel von MainActivity:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    //#####################################################################
    // OnCREATE ###########################################################
    //#####################################################################
    
    public void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        debug = new AlertDialog.Builder(this);
        debug.setMessage("bin da").setCancelable(true);
        debugText = debug.create();
        
        debug2 = new AlertDialog.Builder(this);
        debug2.setMessage("bin auch da").setCancelable(true);
        debugText2 = debug2.create();
        
        //Verbindung zum Speicher aufbauen
        memory = getSharedPreferences("DATA", 0);
        memoryEdit = memory.edit();
        
        
        //Die einzelnen Views variablen zuweisen
        uebersicht = (FrameLayout)findViewById(R.id.Uebersicht);
        termine = (FrameLayout)findViewById(R.id.Termine);
        stundenplan = (FrameLayout)findViewById(R.id.Stundenplan);
        notenverwaltung = (FrameLayout)findViewById(R.id.Notenverwaltung);
        
        
        //neuen GestenScanner
        gestureScanner = new GestureDetector(this);
        
        //Views an Variablen binden
        flipper = (ViewFlipper)findViewById(R.id.flipper);
        
        uebersicht_einstellungen = (FrameLayout)findViewById(R.id.uebersicht_einstellungen);
        uebersicht_einstellungen.setOnClickListener(this);
        
        stundenplan_einstellungen = (FrameLayout)findViewById(R.id.stundenplan_einstellungen);
        stundenplan_einstellungen.setOnClickListener(this);
        
        stundenplan_stundeAdd = (FrameLayout)findViewById(R.id.stundenplan_stundeAdd);
        stundenplan_stundeAdd.setOnClickListener(this);
        
        
        
        
        
        //Einstellungen Laden
        loadSettings();
    }
    
    
    //#####################################################################
    // RÜCKGABEWERT-ACTIVITY ##############################################
    //#####################################################################
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        
        if(requestCode == 1)
            loadSettings();
    }
    
    
    //#####################################################################
    // EINSTELLUNGEN LADEN ################################################
    //#####################################################################
    
    private void loadSettings() {
        
        //Anzeige der Views individuell anzeigen
        if(!memory.getBoolean("check_termine", false)) {
            flipper.removeView(termine);
        }
        else {
            
            if(!termine.getParent().equals(flipper)) {
                
                flipper.addView(termine);
            }
        }
        
        if(!memory.getBoolean("check_stundenplan", false))
            flipper.removeView(stundenplan);
        else {
            
            if(!stundenplan.getParent().equals(flipper))
                flipper.addView(stundenplan);
        }
        
        if(!memory.getBoolean("check_notenverwaltung", false))
            flipper.removeView(notenverwaltung);
        else {
            
            if(!notenverwaltung.getParent().equals(flipper))
                flipper.addView(notenverwaltung);
        }
    }
    
    
    
    //#####################################################################
    // OnClick-Methode ####################################################
    //#####################################################################
    
    @Override
    public void onClick(View eventElement) {
        
        if(eventElement.equals(uebersicht_einstellungen)) {
            
            startActivityForResult(new Intent(this, Settings.class), 1);
        }
        else if(eventElement.equals(stundenplan_einstellungen)) {
            
            startActivityForResult(new Intent(this, Settings.class), 1);
        }
        else if(eventElement.equals(stundenplan_stundeAdd))
            startActivityForResult(new Intent(this, UnterrichtsStundeAdd.class), 2);
            

    }



CodeSchnippsel von Settings:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    //#####################################################################
    // OnCREATE ###########################################################
    //#####################################################################
    
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.settings);
        
        
        debug = new AlertDialog.Builder(this);
        debug.setMessage("Settings: bin da").setCancelable(true);
        debugText = debug.create();
        
        
         memory = getSharedPreferences("DATA", 0);
         memoryEdit = memory.edit();
        
        
        check_stundenplan = (CheckBox)findViewById(R.id.check_stundenplan);
        check_notenverwaltung = (CheckBox)findViewById(R.id.check_notenverwaltung);
        check_termine = (CheckBox)findViewById(R.id.check_termine);
        
        einstellungen_speichern = (Button)findViewById(R.id.einstllungen_speichern);
        einstellungen_speichern.setOnClickListener(this);
        
        loadSettings();
    }

    
    
    
    //#####################################################################
    // OnClick-Methode ####################################################
    //#####################################################################

    @Override
    public void onClick(View eventElement) {
        
        if(eventElement.equals(einstellungen_speichern)) {
            
            memoryEdit.putBoolean("check_stundenplan", check_stundenplan.isChecked());
            memoryEdit.putBoolean("check_notenverwaltung", check_notenverwaltung.isChecked());
            memoryEdit.putBoolean("check_termine", check_termine.isChecked());
            
            
            memoryEdit.commit();
            
            setResult(1);

            finish();
        }
    }
    
    
    
    //Beim erneuten Aufruf von Einstellungen, die Checkboxen so anzeigen, wie der Nutzer sie eingestellt hat
    private void loadSettings() {
        
        check_stundenplan.setChecked(memory.getBoolean("check_stundenplan", true));
        check_notenverwaltung.setChecked(memory.getBoolean("check_notenverwaltung", true));
        check_termine.setChecked(memory.getBoolean("check_termine", true));
    }
}


Ich Hoffe ihr findet meinen Fehler :-)

Wie immer schon mal ein Dankeschön im Voraus!



MfG XoR



UPDATE:

Bin mir nicht mehr so ganz sicher, ob es wirklich an der Methode liegt, welche die RückgabeWerte bearbeidet, denn wenn ich in Settings alles von Zeile 42 bis 47 auskommentiere funktioniert es. Komisch ist nur, dass wenn ich in Zeile 50 einen AlertDialog ausgebe, dieser noch ausgegeben wird (wenn 42 bis 47 nicht auskommentiert ist, und die App abstürtzt).

Vielleicht is hier die LogCat noch hilfreich (YouPlanActivity stellt hierbei die oben genannte MainActivity dar):

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
09-05 21:33:11.894: W/IInputConnectionWrapper(5017): showStatusIcon on inactive InputConnection
09-05 21:33:24.605: D/AndroidRuntime(5101): Shutting down VM
09-05 21:33:24.605: W/dalvikvm(5101): threadid=1: thread exiting with uncaught exception (group=0x40015578)
09-05 21:33:24.609: E/AndroidRuntime(5101): FATAL EXCEPTION: main
09-05 21:33:24.609: E/AndroidRuntime(5101): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=0, data=null} to activity {de.xorstudios.youplan/de.xorstudios.youplan.YouPlanActivity}: java.lang.NullPointerException
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.ActivityThread.deliverResults(ActivityThread.java:2536)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.ActivityThread.handleSendResult(ActivityThread.java:2578)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.ActivityThread.access$2000(ActivityThread.java:117)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:965)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.os.Looper.loop(Looper.java:123)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.ActivityThread.main(ActivityThread.java:3687)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at java.lang.reflect.Method.invokeNative(Native Method)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at java.lang.reflect.Method.invoke(Method.java:507)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at dalvik.system.NativeStart.main(Native Method)
09-05 21:33:24.609: E/AndroidRuntime(5101): Caused by: java.lang.NullPointerException
09-05 21:33:24.609: E/AndroidRuntime(5101):     at de.xorstudios.youplan.YouPlanActivity.loadSettings(YouPlanActivity.java:156)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at de.xorstudios.youplan.YouPlanActivity.onActivityResult(YouPlanActivity.java:118)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.Activity.dispatchActivityResult(Activity.java:3908)
09-05 21:33:24.609: E/AndroidRuntime(5101):     at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
09-05 21:33:24.609: E/AndroidRuntime(5101):     ... 11 more
09-05 21:33:33.039: I/Process(5101): Sending signal. PID: 5101 SIG: 9

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »XoR« (05.09.2012, 21:49)


XoR

Frischling

  • »XoR« ist der Autor dieses Themas
  • Private Nachricht senden

5

06.09.2012, 00:16

Soooo nach einem ganzen Tag am Rande des Wahnsinns habe ich den Fehler endlich durch Zufall, oder eher durch frustriertes rumprobieren gefunden!
In meiner MainActivity musste ich in Zeile 78, 88 und 96 an Stelle von equals() den VergleichungsOperator == verwenden:

Quellcode

1
2
3
4
5
6
7
8
if(!(termine.getParent() == flipper))
            flipper.addView(termine);
        
        if(!(stundenplan.getParent() == flipper))
            flipper.addView(stundenplan);
            
        if(!(notenverwaltung.getParent() == flipper))
            flipper.addView(notenverwaltung);


Warum dies allerdings nur so funktioniert weiß ich auch nicht so recht, wäre also nett wenn mir einer noch fix erklären könnte, warum man hier nicht equals() verwenden darf.
Zudem, warum zeigt Eclipse denn die Fehlerquelle nicht an, finde ich schon ein bischen schwach, oder bin ich einfach nur blind? :-(


MfG XoR :-)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

06.09.2012, 07:01

Du versuchst hoffentlich kein "null.equals(x)", oder? Denn das kann nur in einer NPE enden.
*hochScroll*
Doch, machst Du. Ja, kein Wunder also.
Findbugs hätte das übrigens aufgezeigt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (06.09.2012, 07:07)


Werbeanzeige