onSharedPreferenceChanged niet geactiveerd als wijziging plaatsvindt in afzonderlijke activiteit?

Ik heb onSharedPreferenceChangedgeïmplementeerd in mijn hoofdactiviteit.

Als ik de voorkeuren in de hoofdactiviteit wijzig, wordt mijn evenement geactiveerd.

Als ik de voorkeuren wijzig via mijn voorkeurenscherm (PreferenceActivity), wordt mijn evenement NIET geactiveerd wanneer voorkeuren worden gewijzigd (omdat het een aparte activiteit is en een aparte verwijzing naar sharedPreferences?)

Heeft iemand een aanbeveling hoe ik deze situatie het beste kan oplossen?

Bedankt!

EDIT1: Ik heb geprobeerd de gebeurtenishandler toe te voegen aan mijn voorkeursactiviteit, maar deze wordt nooit geactiveerd. De volgende methode wordt aangeroepen tijdens het aanmaken van mijn voorkeursactiviteit. Als ik waarden verander, wordt het bericht nooit afgedrukt (msg()is een wrapper voor Log.d).

private void registerChangeListener () {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
    sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener () {
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            msg (" ***** Shared Preference Update ***** ");
            Intent i = new Intent();
            i.putExtra("KEY", key);
            i.setAction("com.gtosoft.dash.settingschanged");
            sendBroadcast(i);
            // TODO: fire off the event
        }
    });
}

Antwoord 1, autoriteit 100%

De OnSharedPreferenceChangeListenerwordt in jouw geval verzameld als je een anonieme klas gebruikt.

Om dat probleem op te lossen, gebruikt u de volgende code in PreferenceActivityom een ​​wijzigingslistener aan en uit te schrijven:

public class MyActivity extends PreferenceActivity implements
    OnSharedPreferenceChangeListener {
@Override
protected void onResume() {
    super.onResume();
    // Set up a listener whenever a key changes
    getPreferenceScreen().getSharedPreferences()
            .registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPause() {
    super.onPause();
    // Unregister the listener whenever a key changes
    getPreferenceScreen().getSharedPreferences()
            .unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key) 
{
  // do stuff
}

Houd er verder rekening mee dat de luisteraar alleen wordt gebeld als de werkelijke waarde verandert. Als u dezelfde waarde opnieuw instelt, wordt de luisteraar niet ontslagen.

zie ook SharedPreferences.onSharedPreferenceChangeListener wordt niet consequent aangeroepen


Antwoord 2, autoriteit 12%

Dit gebeurt omdat vuilnisophaler. het werkt maar één keer. dan wordt de referentie verzameld als afval. dus maak een instantieveld voor de luisteraar.

private OnSharedPreferenceChangeListener listner;
listner = new SharedPreferences.OnSharedPreferenceChangeListener() {        
        @Override
        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
            //implementation goes here
        }
    };
    prefs.registerOnSharedPreferenceChangeListener(listner);

Antwoord 3, autoriteit 5%

Ik ben hier aangekomen, net als vele anderen, omdat mijn luisteraar niet wordt ontslagen als ik mijn boolean verander van truein false, of omgekeerd.

Na veel lezen en herstructureren, het wisselen van contexts/innerclasses/privates/static/en dergelijke, realiseerde ik me mijn (domme) fout:

De onSharedPreferenceChangedwordt alleenaangeroepen als er iets verandert. Alleen. Ooit.

Tijdens mijn tests was ik zo dom om de hele tijd op dezelfde knop te klikken, waardoor ik de hele tijd dezelfde booleaanse waarde aan de voorkeur toekende, zodat deze nooit veranderde.

Hopelijk helpt dit iemand!!


Antwoord 4, autoriteit 2%

Een andere manier om het probleem te vermijden, is door van uw activiteit de luisteraarklasse te maken. Aangezien er maar één overschrijfmethode is met een onderscheidende naam, kunt u dit doen:

public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sharedPreferences.registerOnSharedPreferenceChangeListener(this);
        ...
    }
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
    {
        ...
    }
} 

Antwoord 5

Merk op dat de oorspronkelijke vraag sprak over een MainActivity die luistert naar instellingswijzigingen in een PreferenceActivity. De vrager voegde vervolgens een “EDIT1” toe en veranderde de vraag in luisteren in de PreferenceActivity zelf. Dat is gemakkelijker dan het eerste en lijkt te zijn wat alle antwoorden veronderstellen. Maar wat als je nog steeds het vorige scenario wilt?

Nou, het zal ook werken, maar gebruik OnResume() en OnPause() niet om de luisteraar aan en uit te schrijven. Als u dit doet, zal de luisteraar ineffectief zijn omdat de gebruiker de hoofdactiviteit verlaat wanneer ze de voorkeursactiviteit gebruiken (wat logisch is als u erover nadenkt). Dus het zal werken, maar dan zal je MainActivity nog steeds op de achtergrond luisteren, zelfs als de gebruiker het niet gebruikt. Beetje verspilling van middelen, niet? Er is dus een andere oplossing die lijkt te werken, voeg gewoon een methode toe aan OnResume() om alle voorkeuren opnieuw te lezen. Op die manier, wanneer een gebruiker klaar is met het bewerken van voorkeuren in een PreferenceActivity, zal de MainActivity ze oppikken wanneer de gebruiker ernaar terugkeert en je helemaal geen luisteraar nodig hebt.

Iemand laat het me weten als ze een probleem zien met deze aanpak.


Antwoord 6

Waarom voeg je niet gewoon een onSharedPreferenceChangedtoe aan de rest van de activiteiten waar de voorkeuren kunnen veranderen?


Antwoord 7

De garbage collector wist dat… je zou moeten overwegen om in plaats daarvan een applicatiecontext te gebruiken…of voeg gewoon de code toe wanneer de app start… en voeg dan de listener toe met applicatiecontext…


Antwoord 8

Overweeg om PreferencesChangeListenerbinnen de Android App-klasse-instantie te houden. Hoewel het GEEN schone oplossing is om referentie in de App op te slaan, zou GC moeten stoppen met het verzamelen van uw luisteraar en zou u nog steeds DB-wijzigingsupdates moeten kunnen ontvangen. Onthoud dat de voorkeursmanager geeneen sterke verwijzing naar de luisteraar opslaat! (WeakHashMap)

/**
 * Main application class
 */
class MyApp : Application(), KoinComponent {
    var preferenceManager: SharedPreferences? = null
    var prefChangeListener: MySharedPrefChangeListener? = null
    override fun onCreate() {
        super.onCreate()
        preferenceManager = PreferenceManager.getDefaultSharedPreferences(this)
        prefChangeListener = MySharedPrefChangeListener()
        preferenceManager?.registerOnSharedPreferenceChangeListener(prefChangeListener)
    }
}

en

class MySharedPrefChangeListener : SharedPreferences.OnSharedPreferenceChangeListener {
    /**
     * Called when a shared preference is changed, added, or removed.
     */
    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
        if (sharedPreferences == null)
            return
        if (sharedPreferences.contains(key)) {
            // action to perform
        }
    }
}

Other episodes