Wie viele Klassen und Layouts brauche ich für meine App?

  • 37 Antworten
  • Letztes Antwortdatum
Page 4 ist ja eine komplett neue Activity. Diese kann nicht auf die Views der anderen (num im Background liegenden) Activity zugreifen. Deswegen knallt es hier.
 
Hi
Ja @deek hat vollkommen recht.
Wenn du eine neue Activty startest wird die alte zerstört.
Eine Activity ist sozusagen eine abgeschlossene Einheit. Es ist nicht so ohne weiteres möglich auf Elemente einer anderen Activity zuzugreifen.. Schon gar nicht auf Layout, also Viewelement einer anderen Activity.

Das habe ich dir auch schon weiter oben gesagt das man es nicht macht auf View Elemente eines andern Layout einer anderen Klasse zu zugreifen. Das solltest du dir gar nicht erst angewöhnen. was dabei raus kommt siehst du jetzt hier.

Das dies überhaupt funktioniert hat ligt daran das der ViewPager die benachbarten Fragmente schon in den Speicher lädt. Somit sind wenn du auf Seite1 bist die Views von Seite2 schon geladen. aber nicht von Seite3.
Wie gesagt solltest du dir diesen Trick gar nicht erst angewöhnen .
Nur ist es eben so das wenn du mit dem Viewpager arbeitest und ihn auch Seiten vorladen läst sich der life cycle ändert und die Methoden wie onResume() nicht mehr durchlaufen werden.
Ein Beispiel wie du das lösen kannst habe ich dir gegeben.

Ansonsten hast du die Möglichkeit das vorladen zu unterbinden . Dann wird auch die onResume durchlaufen.
Bei „setOffscreenPageLimit(0);” bedeutet 0 das nichts vorgeladen wird und 1 ist der default Wert der eingestellt ist wenn du den Parameter nicht setzt. Habe dir doch die Beschreibung mit gegen und auch den link zur Doku.

Mache dir mal klar was findViewById überhaupt macht. Es sucht in dem aktuell geladenen Layout die Id . Wenn das Layout nicht geladen ist kann es nichts finden gibt null zurück und dann wenn du was in die TextView Schreiben willst kommt logischerweise eine Nullpointer Exception .
 
Danke @deek habe es auch nochmal nachgeschlagen. Stimmt man kann nicht ohne vorladen arbeiten. Ist ja auch klar beim Wischen wird das neue Layout auch schon zu helfte eingeblendet.
 
Hallo,

etwas verwirrend finde ich, dass Android Studio es zulässt, dass ich im Code auf eine id zuweisen kann,
auf die nicht zugegriffen werden kann.
Da die id mit in der Autovervollständigung drin war und es keine Warnung gab, ging ich davon aus,
dass es funktionieren wird.

Ok, ich schätze mal dass ich die Page4 also nicht als Extra Activity verwenden sollte, sondern ebenfalls als Fragment.
Der ViewPager sorgt ja dafür, dass ich zwischen Page1, 2 und 3 hin- und herwischen kann.
Da Page4 aber per Buttonklick angezeigt werden soll, wird der ViewPager mir hier nicht helfen.
Besser gesagt, für die Page4 werde ich den ViewPager nicht benötigen.

In einem Tutorial habe ich gelesen, dass man
MainActivity extends FragmentActivity
verwenden kann, um z.B. auf Knopfdruck zwischen 2 Fragmenten hin- und herzuwechseln (ohne zu wischen).

In meiner MainActivty steht derzeit noch:
public class MainActivity extends AppCompatActivity
Beim Umschreiben dieser Zeile (in FragmentActivity) gibt's schon mal keinen Fehler, was gut ist.

In dem Tutorial war der Button, der für das Wechseln zwischen den Fragmenten verantwortlich ist,
aber nicht im Fragment drin, sondern in der Titelleiste (die Leiste, die den App-Namen enthält.)
(onOptionsItemSelected)
Bei mir sind die Buttons allerdings direkt in den Fragmenten drin.

Ist mein Vorhaben dennoch realisierbar/sinnvoll?

Grüße
 
>etwas verwirrend finde ich, dass Android Studio es zulässt, dass ich im Code auf eine id zuweisen kann, auf die nicht zugegriffen werden kann.

Also der Compiler prüft hier nur ob es die ID überhaupt gibt. Nicht ob es die ID zur Laufzeit auch an der stelle wo du das findViewById() machst auch im Speicher geladen ist. Dafür bist du selber verantwortlich das sicher zu stellen.

Zu Punkt zwei.

Ob du nun eine extra Activity oder ein Fragment machst ist dir überlassen. Wichtig ist nur bei einer extra Activity kannst du nicht auf Elemente der Main oder deiner Fragmente zugreifen.


Es geht nicht den ViewPager und Normale Fragmente zu Mischehen zumindest würde ich dir das als Anfänger nicht empfehlen. Dafür solltest du erst mal die Grundlagen verstanden haben.

Wenn du vier Fragmente in deiner Activity haben willst und sofort auf eine bestimmte Seite gehen willst kannst du "setCurrentItem(int item)" in deinem Button benutzen.
Dafür brauchst du aber den ViewPager aus der MainActivity. Den kannst du dir über den Kontext der Activity mittels findVie… holen.

Es ist aber auch möglich auf die Seite 4 mit wischen zu kommen. Wenn du das nicht willst ist es besser eine eigene Avtivity zu benutzen.
Wenn du wieder mittels Intent zurück zur MainActivity und somit zum ViewPager gehst .
Kannst du ja dem Intent die gewünschte Seite die der Pager gleich öffnen soll mit geben.
Das wertest du in deiner Main aus und setzt die Seite, wurde nichts übergeben begingst du bei Seite eins.
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: no1Ltan und swa00
Hallo,

habe weitere Fortschritte gemacht!

Das Problem, dass sich die layouts von Page1 nicht aktualisieren, habe ich so gelöst:
Diesen Code-Block auf Page_1:
Code:
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_MULTI_PROCESS); // Load saved shared file
        text = prefs.getString("text", text); // Load saved text
        TextView tvMode = getActivity().findViewById(R.id.tv_mode); // Link variable to ID
        tvMode.setText(text); // Change text color of left layout
        Log.wtf("test","text wurde geladen!");
habe ich nicht in die onActivityCreated() geschrieben, sondern in die onResume().

Der Hintergrund wird nun sofort übernommen und ist auch nach Drehen des Handys korrekt.
Super.

Nun habe ich auf Page_3, die bisher nur zur "Deko" da war, RadioButtons hinzugefügt.
Beim Klicken der RadioButtons ändert sich ein Text auf der 2. Page.
Ich habe es auch hinbekommen, dass sich die App merkt, welcher RadioButton angeklickt wurde.
(Auch beim Drehen des Bildschirms und beim Neustarten der App.)

Ich wollte einige Codezeilen in der Page_3 zusammenfassen und überflüssige/doppelte Zeilen entfernen.
Jedoch hänge ich an dieser Stelle fest:
24zx5o4b.png


Die Codes der public void switchToPage2(String text) wollte ich in die public void savePreferences(String key, int value) einfügen.
(Natürlich nicht alle, sondern nur die relevanten).
Ich dachte es sei besser, aus diesen 2 Methoden 1 zu erstellen.

Das Problem ist aber, dass die Methode public void savePreferences dann 3 Werte erwartet,
aber entweder nur 1 Wert (vom ButtonClick) oder 2 Werte (vom RadioButtonClick) erhält.
Wie müsste ich vorgehen?

Die App läuft im Moment übrigens so hier:
(Siehe Anhang) - Upload ging nicht, daher ein Link:
Android App3

Viele Grüße
 
Hallo ja schön.

Was mich nur etwas wundert ist . Weil bei mir die onResume schon ausgeführt wurde bevor ich zur Seite 1 geschoben habe . Wenn ich auf Seite zwei gehe wird gleich die onResume von Seite 1 und 3 ausgeführt. Nach einem Button klick nicht mehr. Auch wenn ich nach dem Klick zur seite 1 wische wird onResum nicht nochmal ausgeführt.

Deshalb hatte ich den code mit Listner gemacht.

Zeige mal bitte deine MainActivity wie du den ViewPager erstellst.
 
Hallo!
Die MainActivity habe ich - soweit ich mich erinnere - nicht mehr verändert.
Code:
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity
{
    ViewPager vp;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager vp = findViewById(R.id.vp);
        SetUpViewPager(vp);
    }
    public void SetUpViewPager(ViewPager viewpage)
    {
        MyViewPagerAdapter Adapter = new MyViewPagerAdapter(getSupportFragmentManager());
        Adapter.AddPageFragment(new Page_1(), "Page 1");
        Adapter.AddPageFragment(new Page_2(), "Page 2");
        Adapter.AddPageFragment(new Page_3(), "Page 3");
        //viewpage.setOffscreenPageLimit(0);
        viewpage.setAdapter(Adapter);
    }
    public class MyViewPagerAdapter extends FragmentPagerAdapter
    {
        private List<Fragment> MyFragment = new ArrayList<>();
        private List<String> MyPageTitle = new ArrayList<>();

        public MyViewPagerAdapter(FragmentManager manager)
        {
            super(manager);
        }
        public void AddPageFragment(Fragment Frag, String Title)
        {
            MyFragment.add(Frag);
            MyPageTitle.add(Title);
        }
        @Override
        public Fragment getItem(int i)
        {
            return MyFragment.get(i);
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position)
        {
            return MyPageTitle.get(position);
        }

        @Override
        public int getCount()
        {
            return 3;
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        int id = item.getItemId();

        if (id == R.id.action_settings)
        {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Hast du eine Idee bezüglich des Zusammenfassens der 2 Methoden in der Page3?
Ich würde gerne die savePreferences und die switchToPage2 zusammenfassen.
(In so fern das sinnvoll ist.)

Edit
Android Studio klappt mir ständig Methoden zusammen.
Was muss ich einstellen, damit alles ausgeklappt bleibt?
Klar kann ich links auf das + klicken, aber auf Dauer wird das ermüdend.

Grüße
 
Habe mir dein Video noch mal genauer angesehen. Das ist ja jetzt auch ein anderes verhalten . Denn von der Seite zwei gehst du nach einen Button klick nicht mehr diereckt zurück zu Seite 1. Sondern erst zu einer anderen Seite oder Activity somit wird beim zurückgehen natürlich die onResume ausgeführt. Bei einem direkten Wechsel von 2 zu 1 wird sie nicht nochmal ausgeführt denn die Seite ist vorgeladen.
Mit dem veränderten verhalten geht es natürlich das solltest du verstanden haben.

Wenn du die Methoden zusammen zusammenfassen willst könntest du es so machen.
Übergebe einer Methode den Key als String und auch für den Wert auch als String.
Du speicherst somit alles als String . Musst natürlich dann wenn du den int Wert brauchst den String int wandeln sowie auch int in String Wandeln .

int i = 10;
String s = String.valueOf(i);

int number = Integer.valueOf(numberAsString);
 
Hallo,

@jogimuc:
Dass die onResume anspringt, sobald man von der Activity zurück ins Fragment springt, ergibt natürlich Sinn.

int i = 10;
String s = String.valueOf(i);
int number = Integer.valueOf(numberAsString);
Das werde ich auf jeden Fall ausprobieren, danke!

@deek:
Hab's mir mal durchgelesen (inkl. des Anfangspost, der ja im Prinzip die gleiche Problematik beschreibt,
wie ich sie vor Kurzem hatte.
Das ist ja schon hohe Schule für einen Anfänger wie mich :)
Ist definitiv interessant, vielen Dank.

@all:
Ich hatte vor Kurzem ja RadioButtons in die Page_3 eingefügt.
Habe es geschafft, dass sie sowohl Änderungen an der Page_2 vornehmen
als auch dass ihr Status gespeichert wird.
Die App merkt sich nach dem Neustart also, welcher RadioButton geklickt wurde.

Zusätzlich habe ich eine neue Page erstellt (Page_5, da Page_4_Colors ja bereits die Activity ist).
Diese besteht aus CheckBoxen, deren Aufgabe es ist, die RadioButtons auf der Page_3 auszublenden (nicht gecheckt)
bzw. einzublenden (gecheckt).
Auch hier habe ich es dank der SharedPreferences geschafft, dass sich die App merkt, welche Checkboxen
gecheckt sind und welche nicht.
Ebenso konnte ich die Sichtbarkeit der RadioBoxen beeinflussen.
(Sowohl direkt - um es sofort zu sehen - als auch mittels SharedPreferences - damit es gespeichert ist.)

Leider habe ich so viel gecodet, dass die App nun abstürzt und ich nicht mehr weiß, wo genau das Problem liegt.
(Ist im Moment auch etwas unordentlich.)
Relevant sind in diesem Fall nur Page_3 und Page_5

Beim Klick auf eine Checkbox in Page_5 übermittele ich die folgenden Werte an die SharedPreferences:
String nr, boolean state, String rbnr, int vis
(Nr. der Checkbox, Status der Checkbox, Nr. des RadioButtons, Sichtbarkeit des RadioButtons)

Page_3.java:
Code:
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

public class Page_3 extends Fragment
{
    RadioGroup radioGroup;
    final String KEY_SAVED_RADIO_BUTTON_INDEX = "SAVED_RADIO_BUTTON_INDEX";
    int vis; // Visibility value received from SharedPreferences
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View PageThree = inflater.inflate(R.layout.page3, container, false);
        radioGroup = PageThree.findViewById(R.id.radio_group);
        radioGroup.setOnCheckedChangeListener(radioGroupOnCheckedChangeListener);
        RadioButton radioButtonA = PageThree.findViewById(R.id.radio_button_A);
        RadioButton radioButtonB = PageThree.findViewById(R.id.radio_button_B);

        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_MULTI_PROCESS); // Load saved shared file
        int savedRadioIndex = prefs.getInt(KEY_SAVED_RADIO_BUTTON_INDEX, 0);
        int visA = prefs.getInt("rbA", vis);
        int visB = prefs.getInt("rbB", vis);
        radioButtonA.setVisibility(visA);
        radioButtonB.setVisibility(visB);
        RadioButton savedCheckedRadioButton = (RadioButton) radioGroup.getChildAt(savedRadioIndex);
        savedCheckedRadioButton.setChecked(true);
        radioButtonA.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                switchToPage2("A");
            }
        });

        radioButtonB.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                switchToPage2("B");
            }
        });
        return PageThree;
    }

    RadioGroup.OnCheckedChangeListener radioGroupOnCheckedChangeListener =
            new RadioGroup.OnCheckedChangeListener()
            {
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId)
                {
                    RadioButton checkedRadioButton = radioGroup.findViewById(checkedId);
                    int checkedIndex = radioGroup.indexOfChild(checkedRadioButton);
                    savePreferences(KEY_SAVED_RADIO_BUTTON_INDEX, checkedIndex);
                }
            };

    public void savePreferences(String key, int value)
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_MULTI_PROCESS); // Create new SharedPreferences instance
        SharedPreferences.Editor editor = prefs.edit();
        editor.putInt(key, value);
        editor.commit();
    }
    public void switchToPage2(String text)
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_MULTI_PROCESS); // Create new SharedPreferences instance
        SharedPreferences.Editor editor = prefs.edit(); // Assign variable to editor function
        editor.putString("text", text); // Write selected position (int) inside of editor
        editor.apply(); // Save values, close process
        TextView tv = getActivity().findViewById(R.id.tv_mode);
        tv.setText(text);
        ViewPager vp = getActivity().findViewById(R.id.vp);
        vp.setCurrentItem(1);
    }
}

Page_5.java:

Code:
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.RadioButton;

public class Page_5 extends Fragment
{
    boolean state; // Checkbox checked/not checked
    String nr;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View PageFive = inflater.inflate(R.layout.page5, container, false);
        CheckBox checkBoxA = PageFive.findViewById(R.id.check_box_A);
        CheckBox checkBoxB = PageFive.findViewById(R.id.check_box_B);

        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", 0);
        SharedPreferences.Editor editor = prefs.edit();
        loadPreferences(); // Load SharedPreferences
        checkBoxA.setChecked(prefs.getBoolean("A", false));
        checkBoxB.setChecked(prefs.getBoolean("B", false));
        checkBoxA.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if (((CheckBox) v).isChecked())
                {
                    RadioButton rba = getActivity().findViewById(R.id.radio_button_A);
                    rba.setVisibility(View.VISIBLE);
                    savePreferences("A", true, "rbA", 0);
                }
                else
                {
                    RadioButton rba = getActivity().findViewById(R.id.radio_button_A);
                    rba.setVisibility(View.GONE);
                    savePreferences("A", false, "rbA", 8);
                }
            }
        });
        checkBoxB.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if (((CheckBox) v).isChecked())
                {
                    RadioButton rbb = getActivity().findViewById(R.id.radio_button_B);
                    rbb.setVisibility(View.VISIBLE);
                    savePreferences("B", true, "rbB", 0);
                }
                else
                {
                    RadioButton rbb = getActivity().findViewById(R.id.radio_button_B);
                    rbb.setVisibility(View.GONE);
                    savePreferences("B", false, "rbB", 8);
                }
            }
        });
        return PageFive;
    }
    public void savePreferences(String nr, boolean state, String rbnr, int vis)
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_MULTI_PROCESS);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putBoolean(nr, state);
        editor.putInt(rbnr, vis);
        editor.apply();
    }
    public void loadPreferences()
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_MULTI_PROCESS);
        state = prefs.getBoolean("state", state);
        nr = prefs.getString("nr", nr);
    }
}

Ich vermute mal, dass der Fehler in Page_5 liegt, da die App immer abstürzt, sobald Page_3 fertig geladen wurde.

Danke für jede Hilfe!

Grüße
 
Hi ohne deinen code jetzt durchgegangen zu sein wieso Page 5 wenn Page 3 geladen wurde lädt er Page 4 und 2 vor nicht Page 5.
[doublepost=1535643244,1535642382][/doublepost]dein Fehler ligt in der Page 3

du willst einen listner setzen der erwartet eine Methode nicht einen Datentyp.
dafür musst du eine Innerere Klasse machen.

Dieser code ist falsch.
radioGroup.setOnCheckedChangeListener(radioGroupOnCheckedChangeListener);

RadioGroup.OnCheckedChangeListener radioGroupOnCheckedChangeListener =
new RadioGroup.OnCheckedChangeListener()
{
@override
public void onCheckedChanged(RadioGroup group, int checkedId)
{
RadioButton checkedRadioButton = radioGroup.findViewById(checkedId);
int checkedIndex = radioGroup.indexOfChild(checkedRadioButton);
savePreferences(KEY_SAVED_RADIO_BUTTON_INDEX, checkedIndex);
}
};

so solte es gehen.

radioGroup.setOnCheckedChangeListener( new radioGroupOnCheckedChangeListener);

class radioGroupOnCheckedChangeListener implements RadioGroup.OnCheckedChangeListener
{
@override
public void onCheckedChanged(RadioGroup group, int checkedId)
{
RadioButton checkedRadioButton = radioGroup.findViewById(checkedId);
int checkedIndex = radioGroup.indexOfChild(checkedRadioButton);
savePreferences(KEY_SAVED_RADIO_BUTTON_INDEX, checkedIndex);
}
}
 
Zuletzt bearbeitet:
Hallo,

ich widerspreche dir nur ungern, aber der Fehler lag in der Page_5.java
Falsch war:
Code:
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", 0);
        SharedPreferences.Editor editor = prefs.edit();
        loadPreferences(); // Load SharedPreferences
        checkBoxA.setChecked(prefs.getBoolean("A", false));
        checkBoxB.setChecked(prefs.getBoolean("B", false));

Richtig(er) ist:
Code:
        loadPreferences(); // Load SharedPreferences
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", 0);
        checkBoxA.setChecked(prefs.getBoolean("A", false));
        checkBoxB.setChecked(prefs.getBoolean("B", false));

Es stürzt jetzt nicht mehr ab!
Der Status der Checkboxen und RadioButtons wird auch korrekt gespeichert.
(Sowohl "on the fly" als auch permanent, damit beim Kippen des Bildschirms alles richtig ist.)

Bei der Sache mit den RadioButtons auf Page_3 kann ich dir weder zustimmen,
noch widersprechen - da fehlt mir einfach die Erfahrung!

Selbstverständlich bin ich dir trotzdem dankbar :)

Grüße
 
Ich kann das nicht richtig glauben das dies der Grund gewesen sein soll. Die Reihen folge solte hier in diesem Fall keine Rolle spielen und auch nicht das du einen Editor erstellst den du nicht benutzt.

Lösche die app vom Handy deinstallieren.
Nun sind deine pref weg. Installire die App neu und der Fehler wird wieder da sein.

Beim schreiben mit editor.apply(); und nicht vorhandenen "Key" kann ein Fehler entstehen.

deshalb benutze ich Commit.

Besser und einfacher läst sich das mit dem Debugger rausfinden als hier so trocken.

Versuche es mit dem deinstalieren dann weisst du es?

to Mountain View, CA on November 7-8, 2018.

  • API level
added in API level 1
SharedPreferences.Editor

public static interface SharedPreferences.Editor

android.content.SharedPreferences.Editor

Interface used for modifying values in a SharedPreferences object. All changes you make in an editor are batched, and not copied back to the original SharedPreferences until you call commit() or apply()

Summary
Public methods
abstract void apply()
Commit your preferences changes back from this Editor to the SharedPreferences object it is editing.


Public methods
apply
added in API level 9
public abstract void apply ()
Commit your preferences changes back from this Editor to the SharedPreferences object it is editing. This atomically performs the requested modifications, replacing whatever is currently in the SharedPreferences.

Note that when two editors are modifying preferences at the same time, the last one to call apply wins.

Unlike commit(), which writes its preferences out to persistent storage synchronously, apply() commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won't be notified of any failures. If another editor on this SharedPreferences does a regular commit() while a apply() is still outstanding, the commit() will block until all async commits are completed as well as the commit itself.

As SharedPreferences instances are singletons within a process, it's safe to replace any instance of commit() with apply() if you were already ignoring the return value.

You don't need to worry about Android component lifecycles and their interaction with apply() writing to disk. The framework makes sure in-flight disk writes from apply() complete before switching states.
 
Zuletzt bearbeitet:
Hallo,

ich erwecke diesen Klassiker mal wieder zum Leben.

Also, erstmal ein großes Dankeschön an alle Helfer!
Sowohl in diesem Thread als auch in anderen Threads.

Ich habe die Strukturen in meinen Codes von Grund auf überarbeitet, so dass ich einen viel besseren Überblick habe.

Leider hänge ich gerade an einer Stelle fest, wo ich nicht weiß, warum der strukurierte Code nicht funktioniert,
aber der lieblos dahin geschriebene hingegen einwandfrei.

Es geht dabei um ein Fragment, in der einige RadioButtons enthalten sind.
Deren Status, welche angeklickt ist und ob sie Sichtbar ist, wird am Anfang ermittelt.
(Die Sichtbarkeit wird über ein anderes Fragment eingestellt - die Werte werden mittels der SharedPreferences geladen.)
Ich muss aber auch ehrlich zugeben, dass die Sache mit den RadioButtons gar nicht sooo einfach ist.
(Für mich zumindest.)

Dieser Code hier funktioniert einwandfrei, jedoch ist die Struktur nicht so, wie ich sie mir wünsche:
Code:
public class Modes extends Fragment
{
    RadioGroup radioGroup;
    final String KEY_SAVED_RADIO_BUTTON_INDEX = "SAVED_RADIO_BUTTON_INDEX";
    String key; // Used for Radio Button Index
    int value; // Checked Index
    int vis; // Visibility value received from SharedPreferences
    SharedPreferences prefs; // SharedPreferences global
    String mode; // Mode of SharedPreferences
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View modes = inflater.inflate(R.layout.modes, container, false);
        radioGroup = modes.findViewById(R.id.radio_group_modes); // Link variable to ID
        RadioButton radioButtonA = modes.findViewById(R.id.radio_button_A); // Link variable to ID
        RadioButton radioButtonB = modes.findViewById(R.id.radio_button_B); // Link variable to ID
        RadioButton radioButtonC = modes.findViewById(R.id.radio_button_C); // Link variable to ID
      
        radioGroup.setOnCheckedChangeListener(radioGroupOnCheckedChangeListener);

        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_PRIVATE); // Load SharedPreferencs global
        mode = prefs.getString("mode", "A"); // Load current mode or default mode (A)
        int savedRadioIndex = prefs.getInt(KEY_SAVED_RADIO_BUTTON_INDEX, 0); // Load index for radio buttons
        int visA = prefs.getInt("rbA", 0); // Load visibility value for A, default value = 0 (VISIBLE)
        int visB = prefs.getInt("rbB", 0); // Load visibility value for B, default value = 0 (VISIBLE)
        int visC = prefs.getInt("rbC", 0); // Load visibility value for C, default value = 0 (VISIBLE)

        radioButtonA.setVisibility(visA); // Set visibility for A
        radioButtonB.setVisibility(visB); // Set visibility for B
        radioButtonC.setVisibility(visC); // Set visibility for C
        RadioButton savedCheckedRadioButton = (RadioButton) radioGroup.getChildAt(savedRadioIndex);
        savedCheckedRadioButton.setChecked(true);

        radioButtonA.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mode = "A";
                savePreferences();
            }
        });
        radioButtonB.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mode = "B";
                savePreferences();
            }
        });
        radioButtonC.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mode = "C";
                savePreferences();
            }
        });
        return modes;
    }
    RadioGroup.OnCheckedChangeListener radioGroupOnCheckedChangeListener =
            new RadioGroup.OnCheckedChangeListener()
            {
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId)
                {
                    RadioButton checkedRadioButton = radioGroup.findViewById(checkedId);
                    int checkedIndex = radioGroup.indexOfChild(checkedRadioButton);
                    key = KEY_SAVED_RADIO_BUTTON_INDEX;
                    value = checkedIndex;
                    savePreferences();
                }
            };
    public void savePreferences()
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", MODE_PRIVATE); // Create new SharedPreferences instance
        SharedPreferences.Editor editor = prefs.edit(); // Editor variable for SharedPreferences
        editor.putString("mode", mode); // Write selected position (int) inside of editor
        editor.putInt(key, value); // Status of specific radio button
        editor.apply(); // Save + close instance
        Intent intent = new Intent(getActivity(), TriggerOnResume.class); // Create intent for running TriggerOnResumeActivity
        getActivity().startActivity(intent); // Run TriggerOnResumeActivity
        ViewPager vp = getActivity().findViewById(R.id.vp); // Link to ViewPager
        vp.setCurrentItem(1); // Switch to page 2
    }
}

Der hier hat zwar eine schöne Struktur, aber die App stürzt mit meinem "Lieblingsfehler" ab:
"java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.RadioButton.setVisibility(int)' on a null object reference"
Code:
public class Modes extends Fragment
{
    RadioGroup radioGroup;
    RadioButton radioButtonA, radioButtonB, radioButtonC; // Mode RadioButtons
    final String KEY_SAVED_RADIO_BUTTON_INDEX = "SAVED_RADIO_BUTTON_INDEX";
    String key; // Used for Radio Button Index
    int value; // Checked Index
    int checkedIndex;
    int savedRadioIndex;
    String mode;
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
    {
        View modes = inflater.inflate(R.layout.modes, container, false); // Link view and layout
        radioGroup = modes.findViewById(R.id.radio_group_modes);

        RadioButton radioButtonA = modes.findViewById(R.id.radio_button_A); // Link variable to ID:
        RadioButton radioButtonB = modes.findViewById(R.id.radio_button_B); // Link variable to ID:
        RadioButton radioButtonC = modes.findViewById(R.id.radio_button_C); // Link variable to ID:
        loadPreferences();
        radioGroup.setOnCheckedChangeListener(radioGroupOnCheckedChangeListener);

        RadioButton savedCheckedRadioButton = (RadioButton) radioGroup.getChildAt(savedRadioIndex);
        savedCheckedRadioButton.setChecked(true);

        radioButtonA.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mode = "A";
                savePreferences();
            }
        });
        radioButtonB.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mode = "B";
                savePreferences();
            }
        });
        radioButtonC.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mode = "C";
                savePreferences();
            }
        });
        return modes;
    }
    RadioGroup.OnCheckedChangeListener radioGroupOnCheckedChangeListener =
            new RadioGroup.OnCheckedChangeListener()
            {
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId)
                {
                    RadioButton checkedRadioButton = radioGroup.findViewById(checkedId);
                    checkedIndex = radioGroup.indexOfChild(checkedRadioButton);
                    key = KEY_SAVED_RADIO_BUTTON_INDEX;
                    value = checkedIndex;
                    savePreferences();
                }
            };
    public void savePreferences()
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", MODE_PRIVATE); // Create new SharedPreferences instance
        SharedPreferences.Editor editor = prefs.edit(); // Editor variable for SharedPreferences
        editor.putString("mode", mode); // Write selected position (int) inside of editor
        editor.putInt(key, value);
        editor.apply(); // Save + close instance
        Intent intent = new Intent(getActivity(), TriggerOnResume.class); // Create intent for running TriggerOnResumeActivity
        getActivity().startActivity(intent); // Run TriggerOnResumeActivity
        ViewPager vp = getActivity().findViewById(R.id.vp); // Link to ViewPager
        vp.setCurrentItem(1); // Switch to page 2
    }
    public void loadPreferences()
    {
        SharedPreferences prefs = getActivity().getSharedPreferences("MY_SHARED_PREF", Context.MODE_PRIVATE); // Load saved shared file
        savedRadioIndex = prefs.getInt(KEY_SAVED_RADIO_BUTTON_INDEX, 0);
        mode = prefs.getString("mode", "A"); // Default value mode A

        int visA = prefs.getInt("rbA", 0); // Default value 0 (visible)
        int visB = prefs.getInt("rbB", 0); // Default value 0 (visible)
        int visC = prefs.getInt("rbC", 0); // Default value 0 (visible)
      
        radioButtonA.setVisibility(visA); // Set visibility for A
        radioButtonB.setVisibility(visB); // Set visibility for B
        radioButtonC.setVisibility(visC); // Set visibility for C
    }
}

Ich hatte auch mehrere Variationen probiert - alles erfolglos.
- visA, visB, visC; global definiert
- loadPreferences() an verschiedenen Stellen aufgerufen

Mag sein, dass ich das Prinzip erst richtig verstehen werde, wenn auch der Code funktioniert.
(Aus dem 1. werde kaum schlau.)
Im Moment ist es zum Teil leider eher ein Ratespiel.

Das Problem bzw. Symptom scheinen auf jeden Fall die 3 hier zu sein:
(Kommentiere ich sie aus, läuft alles.)
Code:
        radioButtonA.setVisibility(visA); // Set visibility for A
        radioButtonB.setVisibility(visB); // Set visibility for B
        radioButtonC.setVisibility(visC); // Set visibility for C
Die Ursache liegt aber sicherlich woanders.

Der RadioButtonChangeListener funktioniert auf jeden Fall - das habe ich geprüft

Danke für jede weitere Hilfe!

Grüße
 
In der onCreate erstellst du drei neue Lokale Varaiablen mit gleichen Namen und setzt diese mit dem findVieById .
Aber in der Methode greifst du auf die globalen nicht gesetzen Variablen zu .

Code:
radioButtonA = modes.findViewById(R.id.radio_button_A); // Link variable to ID:
 radioButtonB = modes.findViewById(R.id.radio_button_B); // Link variable to ID:
 radioButtonC = modes.findViewById(R.id.radio_button_C); // Link variable to ID:

so geifst du auch in der onCreate auf die globalen Variablen zu
 
  • Danke
Reaktionen: no1Ltan
Super, vielen Dank!
Manchmal sieht man den Wald vor lauter Bäumen nicht.
Es funktioniert jetzt. :1f44d:
 

Ähnliche Themen

J
Antworten
5
Aufrufe
656
swa00
swa00
B
Antworten
9
Aufrufe
441
jogimuc
J
Zurück
Oben Unten