Android:Android 4.1 模拟器从 DatePicker 对话框调用 onDateSet 两次

Posted

技术标签:

【中文标题】Android:Android 4.1 模拟器从 DatePicker 对话框调用 onDateSet 两次【英文标题】:Android: Android 4.1 Emulator Invoking onDateSet Twice from DatePicker Dialog 【发布时间】:2012-07-08 04:12:07 【问题描述】:

我的应用程序在我的 android 2.2 模拟器上运行良好。然后我决定在 Android 4.1 模拟器上进行测试。 DatePickerDialog 看起来有点不同,由于某种原因,当我按下“完成”时,onDateSet() 侦听器被调用两次并导致我的应用程序出现问题。

我知道这一点,因为每当我点击“完成”时,代码中显示的日志就会打印两次

mDateSetListener = new DatePickerDialog.OnDateSetListener() 
    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) 
            Log.v("onDateSet", "ENTERED");
            //rest of code...
    ;

Android 2.2 日期选择器

Android 4.1 日期选择器

【问题讨论】:

2012 年 8 月 30 日模拟器上的相同问题 android 4.1,在这里投票code.google.com/p/android/issues/detail?id=34860 Jelly Bean DatePickerDialog --- is there a way to cancel?的可能重复 【参考方案1】:

尝试设置一个布尔值以检查同一对话框中的双重触发。类似于:

Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_YEAR, 1);
final DatePickerDialog dateDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() 
    boolean fired = false;
    public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) 
        Log.i("PEW PEW", "Double fire check");
        if (fired) 
            Log.i("PEW PEW", "Double fire occured. Silently-ish returning");
            return;
         else 
            //first time fired
            fired = true;
        
        //Normal date picking logic goes here
    
, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
dateDialog.show();

TimePickerDialog 的 onTimeSet 也会发生这种双重触发问题,并且此检查也适用于这些问题。

【讨论】:

fired 变量切换回 false 以便 DatePicker 之后继续工作。顺便说一句,问题也出现在 TimePicker 对话框中。 这个变通方法也适用于 TimePicker 对话框,方法是在创建时使用类似的“触发”检查。 OMG - 我一直在疯狂地试图弄清楚为什么日期选择器中的 onDateSet 中的代码不能正常工作,并且在一些 toastMEssages 意识到它被触发了两次之后。非常感谢 - 尝试调试 11 个小时,这就是那个该死的问题。谢谢!!!! 很乐意尽我所能提供帮助。 这是一个不完整的解决方案。 The bug 在按下“完成”按钮和关闭对话框时都在调用 onDateSet()。后者也有问题,因为日期将在用户取消时设置(即按回或在对话框外点击)。此处发布的解决方案无法解决此问题。【参考方案2】:

根据 Ankur Chaudhary 在类似的TimePickerDialog 问题上的精彩answer,如果我们在onDateSet 内部检查给定视图isShown() 与否,它将以最小的努力解决整个问题,无需要扩展选择器或检查代码周围的一些可怕标志,甚至检查操作系统版本,只需执行以下操作:

public void onDateSet(DatePicker view, int year, int month, int day) 
    if (view.isShown()) 
        // read the date here :)
    

当然,根据 Ankur 的回答,onTimeSet 也可以这样做

【讨论】:

【参考方案3】:

我认为这是相关的,我今天开始在 4.1 上进行测试,发现一些 javascript 事件似乎触发了两次。目前主要是点击。 奇怪的是,如果我添加警报,它“有时”会触发一次。 这种行为奇怪地不一致。

javascript 事件仅在 android 4.1 上以这种方式响应。 iPhone 和我迄今为止尝试过的所有以前版本的 android 一样(包括 4.0.x)似乎都很好。

对我来说,这似乎是浏览器或其处理 javascript 的方式出错,但这只是猜测。

【讨论】:

对于如何解决这个错误有什么建议吗?有什么解决方法吗?:) 到目前为止我什么都没找到。除了上述之外,它似乎只发生在点击或触摸事件上。不是所有的事件。 (当我有时间时)我将在 android 错误列表上创建一个错误报告。【参考方案4】:

重申:这是 Android 中已确认的错误。已经提出了两种解决方法,将状态保存在(实例)变量中或询问对话框是否为isShown()。但是isShown() 似乎不可靠(例如,根据this answer's comments),如果您想重新显示对话框,保存状态会变得混乱。 更好的解决方案是将状态保存在 Dialog 本身中:

public void onDateSet(DatePicker picker, int year, int monthOfYear, int dayOfMonth) 
    if (picker.getTag() == null) 
        picker.setTag("TAGGED");
        // Only gets called once per Dialog
    

干净有效。

【讨论】:

以上是关于Android:Android 4.1 模拟器从 DatePicker 对话框调用 onDateSet 两次的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio 4.1+ 模拟器侧边栏?

在Android Studio中将Gradle从3.3升级到4.1后出错

Android studio 4.1 Emulator 扩展控件

pulltorefresh android 4.1及更高版本[重复]

在 Android Studio 1.4.1 中使用 Nexus 10 模拟器忽略 layout-xlarge

从0系统学Android--4.1探究碎片