メインアクティビティに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);
ブール値をtrue
からfalse
に、またはその逆に変更してもリスナーが起動しないため、他の多くの人と同様にここに到着しました。
contexts/inner
classes/privates/static/
などを切り替えて読み、リファクタリングした後、私は(愚かな)エラーに気付きました。
onSharedPreferenceChanged
はonlyが変更された場合に呼び出されます。のみ。今まで。
テスト中、私はいつも同じボタンをクリックするのがとてもつまらなかったので、常に同じブール値を設定に割り当てたため、変更されませんでした。
これが誰かを助けることを願っています!!
問題を回避するもう1つの方法は、アクティビティをリスナークラスにすることです。固有の名前を持つオーバーライドメソッドは1つしかないため、これを行うことができます。
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)
{
...
}
}
PreferenceActivityの設定変更を聞いているMainActivityの元の質問に注意してください。その後、質問者は「EDIT1」を追加し、質問をPreferenceActivity自体で聞くように変更しました。これは前者よりも簡単で、すべての答えが想定しているようです。しかし、前者のシナリオが引き続き必要な場合はどうでしょうか?
まあ、それも動作しますが、OnResume()とOnPause()を使用してリスナーを登録および登録解除しないでください。そうすると、ユーザーがPreferenceActivityを使用するときにMainActivityを離れるので、リスナーは無効になります(これについて考えると理にかなっています)。したがって、動作しますが、ユーザーが使用していない場合でも、MainActivityはバックグラウンドで引き続きリッスンします。リソースの浪費のようなものではありませんか?動作するように思われる別のソリューションがあります。OnResume()にメソッドを追加して、すべての設定を再読み込みします。このようにして、ユーザーがPreferenceActivityの設定の編集を終了すると、MainActivityはユーザーがそれに戻ったときにそれらを取得しますリスナーはまったく必要ありません。
このアプローチに問題がある場合は、誰か教えてください。
設定が変更される可能性のある残りのアクティビティにonSharedPreferenceChanged
を追加しないのはなぜですか?
ガベージコレクターはそれを消去します...代わりにアプリケーションコンテキストの使用を検討する必要があります...または、アプリの起動時にコードを追加するだけで...アプリケーションコンテキストでリスナーを追加します...
PreferencesChangeListenerをAndroid Appクラスインスタンスに保存することを検討してください。 App内の参照は、GCによるリスナーのガベージコレクションを停止し、DB変更の更新を受信できるはずです。設定マネージャーしないリスナーへの強力な参照を保存してください!(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)
}
}
そして
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
}
}
}