【问题标题】:Android Broadcast Receiver SharedPreferences empty on initial Activity's onResumeAndroid Broadcast Receiver SharedPreferences 在初始 Activity 的 onResume 上为空
【发布时间】:2015-06-17 00:48:36
【问题描述】:

这是我在MainActivity 中的onResume 电话:

@Override
public void onResume() {
    super.onResume();

    SharedPreferences settings = context.getSharedPreferences(INSTALL_PREFERENCE, 0);
    String referrerString = settings.getString(REFERRAL_KEY, null);
    Map<String, String> params = new HashMap<~>();
    if (referrerString != null){
         params.put("referrer", referrerString);
    }
}

这是我在扩展BroadcastReceiver 的类中的onResume

@Override
    public void onReceive(Context context, Intent intent){
        try{
            String referrerString = intent.getStringExtra("referrer");

            if(null != referrerString){
                String referrer = URLEncoder.encode(referrerString, "UTF-8");
                context.getSharedPreferences(INSTALL_PREFERENCE, Context.MODE_PRIVATE).edit().putString(REFERRAL_KEY, referrer).commit();
            }

        }
        catch (Exception e){
            //don't handle exceptions for now
        }
    }

问题是当我通过打开应用程序调用MainActivity 时,我的应用程序在第一次打开时不会返回referrerSharedPreferences 不会在第一个打开的应用程序上存储我的referrer 是否有原因?我想在第一次打开而不是第二次时传回 referrer

【问题讨论】:

    标签: android referrer


    【解决方案1】:

    on resume() 将在广播接收器之前执行,因此您可能第一次收到引荐来源网址的 null 或默认值,如果您重新打开活动,您可能会获得正确的值,因为 onReceive () 会在这个时候执行。

    如果您的应用程序有任何设置首选项屏幕,它实际上仅在打开后才初始化设置,因此您可能必须在使用之前使用默认值初始化所有首选项。这可能是有时如果您打开应用程序会得到正确值的原因,因为您可能已经打开了设置屏幕。

    【讨论】:

    • 有没有办法确保我可以在第一个应用打开时得到这个?
    • 你知道这种行为记录在哪里吗?
    • 没有记录,而是我的个人经历
    • 你是如何测试这个的?
    • 在应用程序启动时,您应该能够每次都读取正确的首选项值。休息一下,您就会知道预期的结果是什么
    【解决方案2】:

    这是您可以修复它的一种方法。让你的Activity实现OnSharedPreferenceChangeListener接口,当SharedPreference文件中注册的任何值发生变化时,它将调用onSharedPreferenceChanged()回调。

    如果时机合适并且您在onResume() 中获得了一个值,那么就按照您在当前代码中所做的那样继续。

    如果您还没有值,则显示 ProgressDialog,并等待 BroadcastReceiver 填充该值。 值被BroadcastReceiver修改后,捕获onSharedPreferenceChanged()中的值,然后根据需要使用。

    这是解决方案的一般结构:

    public class MainActivity extends Activity
            implements SharedPreferences.OnSharedPreferenceChangeListener {
    
        SharedPreferences settings;
        ProgressDialog dialog;
        Map<String, String> params;
        String INSTALL_PREFERENCE = "installpref";
        String REFERRAL_KEY = "referral";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dialog = new ProgressDialog(this);
            params = new HashMap<String, String>();
    
            settings = this.getSharedPreferences(INSTALL_PREFERENCE, 0);
    
            settings.registerOnSharedPreferenceChangeListener(this); //added
        }
    
        @Override
        public void onResume() {
            super.onResume();
    
            String referrerString = settings.getString(REFERRAL_KEY, null);
            if (referrerString != null){
                params.put("referrer", referrerString);
                //call whatever methods need params to have a value
                //.......
            }
            else{
                //Show progress dialog and wait for BroadcastReceiver to populate referrer
                dialog.setMessage("loading");
                dialog.show();
            }
        }
    
    
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key) {
    
            if (key.equals(REFERRAL_KEY)){
    
                //dismiss dialog if it's showing
                if (dialog.isShowing()){
                    dialog.dismiss();
                }
    
                String referrerString = sharedPrefs.getString(REFERRAL_KEY, null);
                if (referrerString != null){
                    params.put("referrer", referrerString);
                    //call whatever methods need params to have a value
                    //.......
                }
            }
        }
    }
    

    【讨论】:

    • 不确定这实际上如何改变任何东西,因为应用程序将启动并且主要活动将运行所有回调而不存储共享首选项。
    • @locoboy 你不能延迟 Activity 的生命周期(你也不想),所以最好的办法是给用户反馈你正在等待什么,然后得到尽快获取值,然后在获取值后更新 UI。
    • 问题不是我想给用户反馈,问题是referrer 是我在第一次应用启动时需要在MainActivity 中的东西。我也不想等待它并让应用程序的其余部分挂起。
    • @locoboy 这就是这个解决方案的重点,它使 MainActivity 能够在不使应用挂起的情况下尽快获取值。
    【解决方案3】:

    referrer 广播会在您的应用的主要组件启动后稍稍发送。因此,您必须在收到广播后通知您的活动。
    一种简单的解决方案是在 Receiver 和 Activity 之间使用 LocalBroadcastManager:

    /* BroadcastReceiver */
    
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle extras = intent.getExtras();
        String referrer = (String) extras.get(KEY_REFERRER);
        // save String to SharedPrefrences
        Intent intent = new Intent(ACTION_UPDATE);
        intent.putExtra(KEY_REFERRER, referrer);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }
    
    /*****/
    
    /* Activity*/
    
    private final BroadcastReceiver mUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String referrer = intent.getStringExtra(KEY_REFERRER);
        }
    };
    
    @Override
    protected void onPause() {
       LocalBroadcastManager.getInstance(this).unregisterReceiver(mUpdateReceiver);
        super.onPause();
    }
    
    @Override
    protected void onResume() {
        LocalBroadcastManager.getInstance(this).registerReceiver(mUpdateReceiver, new IntentFilter(ReferrerReceiver.ACTION_UPDATE));
        super.onResume();
    }
    

    如果您需要功能齐全的示例代码/应用程序,请查看我在 GitHub 上的 OpenSource 项目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-07
      • 2023-01-10
      • 1970-01-01
      相关资源
      最近更新 更多