programing

별도의 활동에서 변경이 발생하면 onSharedPreferenceChanged가 실행되지 않습니까?

nasanasas 2020. 11. 7. 10:10
반응형

별도의 활동에서 변경이 발생하면 onSharedPreferenceChanged가 실행되지 않습니까?


onSharedPreferenceChanged내 주요 활동을 구현 했습니다.

기본 활동에서 기본 설정을 변경하면 이벤트가 실행됩니다.

기본 설정 화면 ( PreferenceActivity)을 통해 기본 설정을 변경하면 기본 설정이 변경 될 때 내 이벤트가 실행되지 않습니다 (개별 활동이고 sharedPreferences에 대한 별도의 참조이기 때문입니까?).

이 상황을 극복하는 방법에 대한 권장 사항이 있습니까?

감사!

EDIT1 : 내 기본 설정 활동에 이벤트 처리기를 추가하려고 시도했지만 실행되지 않습니다. 내 환경 설정 활동의 onCreate 중에 다음 메소드가 호출됩니다. 값을 변경하면 메시지 msg()인쇄되지 않습니다 ( 은 래퍼입니다 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
        }
    });
}

OnSharedPreferenceChangeListener익명 클래스를 사용하는 경우 귀하의 경우에 수집 된 쓰레기를 가져옵니다.

이 문제를 해결하려면에서 다음 코드를 사용하여 PreferenceActivity변경 리스너를 등록 및 등록 취소하십시오.

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
}

또한 리스너는 실제 값이 변경된 경우에만 호출됩니다. 동일한 값을 다시 설정하면 리스너가 실행되지 않습니다.

SharedPreferences.onSharedPreferenceChangeListener가 일관되게 호출되지 않음을 참조하십시오.


이것은 가비지 수집기 때문에 발생합니다. 한 번만 작동합니다. 그런 다음 참조는 쓰레기로 수집됩니다. 그래서 리스너에 대한 인스턴스 필드를 만듭니다.

private OnSharedPreferenceChangeListener listner;

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

다른 많은 사람들과 마찬가지로 여기에 도착했습니다. 부울을에서 truefalse또는 그 반대로 변경해도 내 청취자가 해고되지 않기 때문 입니다.

많은 읽기, 리팩토링, 전환 contexts/inner classes/privates/static/등을 한 후 (어리석은) 오류를 깨달았습니다.

onSharedPreferenceChanged됩니다 무언가가 변경되는 경우라고합니다. 뿐. 이제까지.

테스트 중에 항상 같은 버튼을 클릭하는 것이 너무 멍청해서 항상 동일한 부울 값을 기본 설정에 할당했기 때문에 변경되지 않았습니다.

이것이 누군가를 돕기를 바랍니다 !!


문제를 피하는 또 다른 방법은 활동을 리스너 클래스로 만드는 것입니다. 고유 한 이름을 가진 재정의 메서드가 하나뿐이므로 다음과 같이 할 수 있습니다.

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)
    {
        ...
    }
} 

Note the original question spoke of a MainActivity listening to setting changes in a PreferenceActivity. The asker then added an "EDIT1" and changed the question to listening in the PreferenceActivity itself. That is easier than the former and seems to be what all the answers assume. But what if you still want the former scenario?

Well, it will work too, but do not use OnResume() and OnPause() to register and unregister the listener. Doing so will cause the listener to be ineffectual because the user leaves the MainActivity when they use the PreferenceActivity (which makes sense when you think about it). So it will work, but then your MainActivity will still be listening in the background even when the user is not using it. Kind of a waste of resources isn't it? So there is another solution that seems to work, simply add a method to OnResume() to re-read all preferences. That way when a user finishes editing preferences in a PreferenceActivity, the MainActivity will pick them up when the user returns to it and you don't need a listener at all.

Someone please let me know if they see a problem with this approach.


Why don't you just add a onSharedPreferenceChanged in the rest of the activities where the preferences could change?


The garbage collector erases that... you should consider using an Application context instead...or just add the code when app launchs... and then add the the listener with application context...


Consider keeping PreferencesChangeListener inside Android App class instance. Although it's NOT a clean solution storing reference inside App should stop GC from garbage collecting your listener and you should still be able to receive DB change updates. Remember that preference manager does not store a strong reference to the listener! (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)
    }
}

and

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
        }
    }
}

While reading Word readable data shared by first app,we should

Replace

getSharedPreferences("PREF_NAME", Context.MODE_PRIVATE);

with

getSharedPreferences("PREF_NAME", Context.MODE_MULTI_PROCESS);

in second app to get updated value in second app.

참고URL : https://stackoverflow.com/questions/3799038/onsharedpreferencechanged-not-fired-if-change-occurs-in-separate-activity

반응형