Подтвердить что ты не робот

Работа с устаревшими методами в android


В настоящее время я создаю приложение для таргетинга API 23 с минимальным API 19.
В API 23 были заменены некоторые из методов компонента android.widget.TimePicker.

Например:

TimePicker.getCurrentHour();

был заменен на:

TimePicker.getHour();

Теперь, когда я использую TimePicker в своем приложении, я должен проверить, использует ли устройство API 22 или выше со следующим оператором if:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        TimePicker.getHour();
    else
        TimePicker.getCurrentHour();

То, что я сделал, - это расширение класса TimePicker и реализация устаревших методов следующим образом:

public class TimePicker extends android.widget.TimePicker {

    public TimePicker(Context context) {
        super(context);
    }

    public void setCurrentHour(int hour) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            super.setHour(hour);
        else
            super.setCurrentHour(hour);
    }

    public void setCurrentMinute(int minute) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            super.setMinute(minute);
        else
            super.setCurrentMinute(minute);
    }

    public int getCurrentHour() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            return super.getHour();
        else
            return super.getCurrentHour();
    }

    public int getCurrentMinute() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            return super.getMinute();
        else
            return super.getCurrentMinute();
    }
}

поэтому пользователь, который использует этот класс, не повлияет на изменение методов (он должен заменить импорт класса TimePicker в его реализацию).

Правильно ли это? или есть лучшее решение?

Спасибо

4b9b3361

Ответ 1

То, как вы это сделали, является хорошей практикой, насколько я могу читать из показанной части.

Однако, как я видел до сих пор, наилучшей практикой было создание разных подразделений из каждого класса, который вы планируете публиковать, и складывать программу во время установки.

В основном это означает, что if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) находится в верхней части класса.

Если ваш проект намеревается перейти под более разные версии, я предлагаю следующее:

public class Example extends moreExamples implements additionalExamples{
   switch(Build.VERSION.SDK_INT){
      case Build.VERSION_CODES.M:
         codeVersionM();
         break;
      case Build.VERSION_CODES.L:
         codeVersionL();
         break;
      case Build.VERSION_CODES.K:
         codeVersionK();
         break;
      default:
         errorNoBuildImplemented();
   }
}

Ответ 2

Что вы сделали, хорошо, но, вероятно, не лучшее решение, потому что:

  • Вы используете старые имена методов вместо новых
  • Создание настраиваемого класса заставляет вас использовать этот пользовательский класс в своих макетах и ​​кодексе взамен класса framework. Он предпочитает избегать создания пользовательских представлений, если вы можете.

Обычно существует 2 рекомендуемых способа:

1) Продолжайте использовать устаревший метод, пока не обновите свой minSDK. Он будет вызывать новый метод внутренне в новой реализации:

@Deprecated
public void setCurrentHour(@NonNull Integer currentHour) {
    setHour(currentHour);
}

2) Создайте статический вспомогательный класс, который вызовет правильный метод в соответствии с версией SDK. Это то, что библиотека поддержки делает для многих классов уже (TextViewCompat, ViewCompat,...):

public class TimePickerCompat {

    public static void setHour(TimePicker timePicker, int hour) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            timePicker.setHour(hour);
        } else {
            timePicker.setCurrentHour(hour);
        }
    }

}

Ответ 3

Лучше использовать новые имена методов. Таким образом, вы можете в конечном итоге избавиться от своего класса совместимости, когда поднимете версию min sdk до 23, без необходимости менять код, отличный от вашего импорта.

@SuppressWarnings("deprecation")
public class TimePicker extends android.widget.TimePicker
{
    public TimePicker(Context context)
    {
        super(context);
    }

    public TimePicker(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public TimePicker(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public void setHour(int hour)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            super.setHour(hour);
        else
            super.setCurrentHour(hour);
    }

    public void setMinute(int minute)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            super.setMinute(minute);
        else
            super.setCurrentMinute(minute);
    }

    public int getHour()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            return super.getHour();
        else
            return super.getCurrentHour();
    }

    public int getMinute()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            return super.getMinute();
        else
            return super.getCurrentMinute();
    }
}