【问题标题】:Listening for Preference Changes using Mono for Android使用 Mono for Android 监听偏好变化
【发布时间】:2012-05-10 18:35:37
【问题描述】:

我正在尝试从Professional Android Programming with Mono for Android and .Net/C# 书中获取一个示例 (第 202 至 204 页)工作。

要注册和注销更改侦听器,它会显示以下代码示例:

using System;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Preferences;

namespace MonoForAndroidPreferences
{
    [Activity(Label = "User Preferences")]
    public class UserPreferences : PreferenceActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Create your application here
            this.AddPreferencesFromResource(Resource.Layout.userpreferences);
        }

        protected override void OnResume()
        {
            base.OnResume();

            this.GetPreferences(FileCreationMode.Private).RegisterOnSharedPreferenceChangeListener(this);
        }

        protected override void OnPause()
        {
            base.OnPause();

            this.GetPreferences(FileCreationMode.Private).UnregisterOnSharedPreferenceChangeListener(this);
        }

        public void OnSharedPreferenceChanged(ISharedPreferences prefs, string key)
        {
            // Do something with the changed value pointed to by key
        }
    }
}

RegisterOnSharedPreferenceChangeListenerUnregisterOnSharedPreferenceChangeListener 当然不能从UserPreferences 转换为ISharedPreferencesOnSharedPreferenceChangeListener

我不确定作者是如何让它起作用的。任何帮助将不胜感激。

我也尝试从wrox.com 下载示例代码,但它不包括示例代码中的监听偏好更改。

编辑:

以下代码可以编译,但在首选项中进行更新时,OnSharedPreferenceChanged 永远不会被调用。

    public class UserPreferences : PreferenceActivity, ISharedPreferencesOnSharedPreferenceChangeListener
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Create your application here
            this.AddPreferencesFromResource(Resource.Layout.userpreferences);
        }

        protected override void OnResume()
        {
            base.OnResume();

            this.GetPreferences(FileCreationMode.Private).RegisterOnSharedPreferenceChangeListener(this);
        }

        protected override void OnPause()
        {
            base.OnPause();

            this.GetPreferences(FileCreationMode.Private).UnregisterOnSharedPreferenceChangeListener(this);
        }

        void ISharedPreferencesOnSharedPreferenceChangeListener.OnSharedPreferenceChanged(ISharedPreferences prefs, string key)
        {
            // Do something with the changed value pointed to by key
        }
    }

【问题讨论】:

    标签: android xamarin.android


    【解决方案1】:

    我正在处理完全相同的示例,并且触发 OnPause 和 OnResume 事件没有问题。

    问题是在暂停/恢复时注册/取消注册监听器有效,但绝对没有效果。侦听器本身从未被解雇。

    切换到实际的 UserPreferences 意图导致 OnPause 触发,取消注册侦听器。反之亦然,当我从那里回来时。但这只是问题的一部分。我什至无法使用此方法正确加载首选项

    this.GetPreferences(FileCreationMode.Private).RegisterOnSharedPreferenceChangeListener(this);
    

    (我认为原因是因为我使用的活动名称不同,启动器名为PreferencesDemoActivity,而首选项本身由UserPreferences 处理 - 见下文)。

    不幸的是,解决方案标记为上面的答案

    PreferenceScreen.SharedPreferences.RegisterOnSharedPreferenceChangeListener(this);
    

    也不起作用(它抱怨 SharedPreferences 在静态上下文中不可用)。

    一旦我将所有 OnPause/OnResume/Listener 代码移到了 UserPreferences 类的内部,一切都运行良好。

    但是,这对我没有好处。我需要我的 MAIN 应用程序立即响应对首选项的更改,而不必在从首选项屏幕返回时重新阅读它们并检查更改。

    当我的(单独的)首选项屏幕中的某些内容发生更改时,我可以让我的“主”类中的实际 OnSharedPreferenceChanged 监听器触发的唯一方法是这样实现它:

    [Activity(Label = "More user preferences", MainLauncher = true, Icon = "@drawable/icon")]
    public class PreferencesDemoActivity : Activity, ISharedPreferencesOnSharedPreferenceChangeListener
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
    
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
    
            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button>(Resource.Id.MyButton);
    
            // !!!NB !!! Remember to implement ISharedPreferencesOnSharedPreferenceChangeListener in this class, 
            // or you'll never get to OnSharedPreferenceChanged method
            PreferenceManager.GetDefaultSharedPreferences(this).RegisterOnSharedPreferenceChangeListener(this);
    
            button.Click += delegate
                                {
                                    Intent i = new Intent(this, new UserPreferences().Class);
                                    this.StartActivityForResult(i, 0); // this ensures that we come back to this one when we exit the pref screen
                                };
    
        }
    
    
        /// <summary>
        /// Remember to implement ISharedPreferencesOnSharedPreferenceChangeListener in this class, or you'll never get this method to compile
        /// </summary>
        /// <param name="sharedPreferences"></param>
        /// <param name="key"></param>
        public void OnSharedPreferenceChanged(ISharedPreferences sharedPreferences, string key)
        {
            Log.Debug("MUP", string.Format("Preference {0} changed", key));
    
            if (key == "PREF_AUTO_UPDATE")
            {
                bool autoRefresh = sharedPreferences.GetBoolean("PREF_AUTO_UPDATE", false);
                Log.Debug("MUP", string.Format("Preference {0} changed to {1}", key, autoRefresh));
            }
    
        }
    

    这对我有用,并解决了我的问题。关键似乎是使用 PreferenceManager.GetDefaultSharedPreferences

    【讨论】:

    • 这似乎确实是解决方案。想补充一点,按照书中的建议在 onPause 中取消注册处理程序也可以防止调用 OnSharedPreferenceChangd
    【解决方案2】:

    你需要使用

    PreferenceScreen.SharedPreferences.RegisterOnSharedPreferenceChangeListener(this);
    

    而不是

     this.GetPreferences(FileCreationMode.Private).RegisterOnSharedPreferenceChangeListener(this);
    

    【讨论】:

    • SharedPreferences 不是 PreferenceScreen 类的静态属性,所以我看不出这段代码是如何工作的
    【解决方案3】:

    正如您所注意到的,您需要为这些方法提供一个实现ISharedPreferencesOnSharedPreferenceChangeListener 的类的实例。这可以是一个单独的类,或者如果您想在该示例中使用“this”,请修改该类以实现该接口:

    [Activity(Label = "User Preferences")]
    public class UserPreferences : PreferenceActivity, ISharedPreferencesOnSharedPreferenceChangeListener
    {
        // OnCreate, OnResume, etc
    
        public void OnSharedPreferenceChanged(ISharedPreferences sharedPreferences, string key)
        {
        }
    }
    

    【讨论】:

    • 谢谢。根据您的建议,我使用“void ISharedPreferencesOnSharedPreferenceChangeListener.OnSharedPreferenceChanged(ISharedPreferences prefs, string key)”对其进行编译。但是在进行更新时它永远不会被调用。
    【解决方案4】:

    这可能是issue I had with my Samsung Galaxy Nexus 的症状。当我将一个应用程序(在较旧的 Android 2.3.4 手机上运行良好)调试到 Andriod 4.0.2 手机时,OnStartOnResumeOnPauseOnStop 事件都没有被触发全部。

    如果您正在使用这样的新手机,请尝试在 Mono for Android 项目属性中添加“armeabi-v7a”作为支持的架构。

    根据您的支持需求,您可以just offer the "armeabi-v7a" architecture

    【讨论】:

      猜你喜欢
      • 2012-11-15
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      • 2013-01-05
      • 2013-03-10
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      相关资源
      最近更新 更多