代码之家  ›  专栏  ›  技术社区  ›  Brad Hein

如果在单独的活动中发生更改,是否未激发onSharedPreferenceChanged?

  •  66
  • Brad Hein  · 技术社区  · 14 年前

    我已经实现了 onSharedPreferenceChanged 在我的主要活动中。

    如果我通过首选项屏幕更改首选项( PreferenceActivity )我的事件不会在首选项更改时触发(因为它是一个单独的活动和对SharedReferences的单独引用?)

    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
            }
        });
    }
    
    9 回复  |  直到 14 年前
        1
  •  142
  •   Community CDub    7 年前

    这个 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 not being called consistently

        2
  •  17
  •   hderanga    12 年前

    这是因为垃圾收集器。它只工作一次。然后将引用作为垃圾收集。所以为侦听器创建实例字段。

    private OnSharedPreferenceChangeListener listner;
    
    listner = new SharedPreferences.OnSharedPreferenceChangeListener() {        
            @Override
            public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
                //implementation goes here
            }
        };
        prefs.registerOnSharedPreferenceChangeListener(listner);
    
        3
  •  7
  •   Math user2900037    11 年前

    我来到这里,和其他许多人一样,因为我的听众不会因为我把布尔值从 true false ,或副总裁。

    经过大量阅读,重构,转换 contexts/inner classes/privates/static/

    这个 onSharedPreferenceChanged 只有 如果有什么变化就打电话。只是。永远不会。

        4
  •  3
  •   Steve Waring    9 年前

    另一种避免问题的方法是使您的活动成为listener类。由于只有一个重写方法具有独特的名称,因此可以执行以下操作:

    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)
        {
            ...
        }
    } 
    
        5
  •  1
  •   trans    8 年前

    注意,原来的问题谈到了一个main活动,它在PreferenceActivity中监听设置更改。然后提问者添加了一个“EDIT1”,并将问题改为在PreferenceActivity中倾听。这比前者容易,似乎是所有答案的假设。但如果你还想要前一种情况呢?

    当然,它也可以工作,但是不要使用OnResume()和OnPause()来注册和注销侦听器。这样做会导致监听器无效,因为用户在使用PreferenceActivity时会离开MainActivity(这在您考虑它时是有意义的)。所以它会工作,但是你的主要活动仍然会在后台监听,即使用户没有使用它。有点浪费资源,不是吗?所以有另一个解决方案似乎可行,只需在OnResume()中添加一个方法来重新读取所有首选项。这样,当用户在PreferenceActivity中完成对首选项的编辑时,当用户返回到MainActivity时,MainActivity将拾取这些首选项,然后您可以使用它们 .

    如果有人发现这种方法有问题,请告诉我。

        6
  •  0
  •   Cristian    14 年前

    你为什么不加一个 onSharedPreferenceChanged

        7
  •  0
  •   superUser    8 年前

    垃圾收集器会删除。。。你应该考虑改用应用程序上下文…或者只是在应用程序启动时添加代码。。。然后用应用程序上下文添加侦听器。。。

        8
  •  0
  •   kosiara - Bartosz Kosarzycki    6 年前

    考虑保留 首选项更改侦听器 应用程序 类实例。虽然它不是一个干净的解决方案,但在应用程序中存储引用应该可以阻止GC垃圾收集侦听器,并且您应该仍然能够接收DB更改更新。还记得偏好管理器吗 存储对侦听器的强引用!( 懦夫地图

    /**
     * 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
            }
        }
    }
    
        9
  •  -2
  •   Shridutt Kothari    8 年前

    getSharedPreferences("PREF_NAME", Context.MODE_PRIVATE);
    

    具有

    getSharedPreferences("PREF_NAME", Context.MODE_MULTI_PROCESS);