【问题标题】:Android IllegalArgumentException for Date picker日期选择器的 Android IllegalArgumentException
【发布时间】:2017-04-10 12:08:44
【问题描述】:

我用于活动的日期选择器在 KitKat 上崩溃了,但在所有其他较新的操作系统上都可以使用。这是我在旧设备上遇到的例外情况:

java.lang.IllegalArgumentException: fromDate: Mon Apr 10 07:59:25 EDT 2017 年不早于日期:Mon Apr 10 07:59:25 EDT 2017

代码块堆栈跟踪指向:

private void showDatePicker(){
   DatePickerDialog datePickerDialog = new DatePickerDialog(
   getActivity(), this, calendar.get(Calendar.YEAR),  calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
   //this is where the crash happens
   datePickerDialog.getDatePicker().setMinDate(new Date().getTime());
   datePickerDialog.show();
}

请让我知道有关问题的信息是否足够。有什么解决办法吗?

【问题讨论】:

标签: java android datepicker


【解决方案1】:

我通过延迟解决了这个问题:

private void showDatePicker(){
   DatePickerDialog datePickerDialog = new DatePickerDialog(
   getActivity(), this, calendar.get(Calendar.YEAR),  calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
   //this is where the crash happens
   datePickerDialog.getDatePicker().setMinDate(new Date().getTime() - 10000);
   datePickerDialog.show();

}

【讨论】:

  • 发生这种情况的任何原因?这也会影响新设备/操作系统上的行为吗?
  • 在我的应用程序中,此修复对新设备/操作系统没有影响。我认为这是因为 Android 无法设置与当前日期相同的最小日期。
  • @Dinuka 发生这种情况是由于 API21 之前的 CalendarView 中的错误,以及 API21 的 calendarViewMode == MODE_HOLO 中的错误。对于较新版本的 SDK,CalendarView 的代码不同,不包含问题
【解决方案2】:

为了解决这个问题,在 DatePickerDialog 实例化之前为 minDate 创建一个时间戳:

private void showDatePicker(){
   long now = System.currentTimeMillis();
   DatePickerDialog datePickerDialog = new DatePickerDialog(
      getActivity(), this, calendar.get(Calendar.YEAR),  calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
   datePickerDialog.getDatePicker().setMinDate(now);
   datePickerDialog.show();
}

发生此崩溃的原因是在 API21 之前的 CalendarView 和 API21 的 calendarViewMode == MODE_HOLO 中存在错误。

虽然setMinDate 包含一个用注释突出显示的更正:

public void setMinDate(long minDate) {
    ...
    mMinDate.setTimeInMillis(minDate);
    // make sure the current date is not earlier than
    // the new min date since the latter is used for
    // calculating the indices in the adapter thus
    // avoiding out of bounds error
    Calendar date = mAdapter.mSelectedDate;
    if (date.before(mMinDate)) {
        mAdapter.setSelectedDay(mMinDate);
    }
    // reinitialize the adapter since its range depends on min date
    mAdapter.init();

setSelectedDay 中的检查仅比较 mMinDatemSelectedDate 的日期准确性:

public void setSelectedDay(Calendar selectedDay) {
    if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR)
            && selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) {
        return;
    }

mSelectedDatemMinDate 指向同一天,因此mSelectedDate 将保持不变(即处于错误状态mSelectedDate < mMinDate)。

然后控制流将运行到mAdapter.init,然后进入getWeeksSinceMinDate。在此函数中,mMinDatemSelectedDate 的比较将以毫秒精度执行:

private int getWeeksSinceMinDate(Calendar date) {
    if (date.before(mMinDate)) {
        throw new IllegalArgumentException("fromDate: " + mMinDate.getTime()
                + " does not precede toDate: " + date.getTime());
    }

因为mSelectedDatemMinDate 之前的几毫秒内初始化,所以会发生崩溃。

在较新的实现中,此代码已被重写,因此 API21+ 缺少此问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多