Как android.support нарушает безопасность типов Javas? - PullRequest
0 голосов
/ 12 декабря 2018

Сегодня я столкнулся с очень странным поведением.Я знаю, что использую устаревшие API, но, тем не менее, это не должно быть возможным из моего понимания.

У меня есть android.preference.PreferenceActivity, в который я вставил следующий xml через addPreferenceFromResource:

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <EditTextPreference
        android:id="@+id/et_server_endpoint"
        android:key="server_endpoint"
        android:hint="http://192.168.100.42:8080"
        android:title="Server Endpoint"
        android:summary="Sets the Server Endpoint for the search"
        android:dialogTitle="Server Endpoint Settings"
        android:dialogMessage="Set the Servers endpoint"
        />
    <SeekBarPreference
        android:id="@+id/sb_phone_threshold"
        android:key="match_treshold"
        android:title="Matching Threshold"
        android:summary="Sets the minimum Score for matches"
        android:defaultValue="60"
        android:min="40"
        android:max="90"
        app:adjustable="true"
        app:showSeekBarValue="true"/>  
</PreferenceScreen>

Обратите внимание, что SeekBarPreference - это android.support.v7.preference.Preference

У меня нет проблем с надуванием xml.Экран показывает, как ожидалось.Проблема возникает, когда я хочу получить ссылку на нее:

PreferenceActivity.findPreference(key) должен возвращать класс android.preference.Preference (который не является SeekBarPreference).

, но этот кодвозвращает действительный Pref:

 Preference match_treshold = findPreference("match_treshold");

Мне не разрешено разыграть его:

 if (match_treshold instanceof SeekBarPreference){}

из-за

Ошибка: несовместимые типы: Предпочтение не можетбыть преобразованным в SeekBarPreference

Но, что удивительно, если я отлаживаю код, я получаю это Debugging SeekBarPreference

В нем говорится, что класс android.preference.SeekbarPreference.Если я в Google, все, что я могу найти, это https://developer.android.com/reference/android/support/v7/preference/SeekBarPreference

, который утверждает, что он основан на android.preference.SeekBarPreference.Но я не могу найти этот конкретный класс.

Кроме - с моей точки зрения - плохого дизайнерского решения не наследовать support.v7 Предпочтения от Android: Что, черт возьми, там происходит?

РЕДАКТИРОВАТЬ: Из-за запроса я публикую класс Activity

package com.my.company.domain.namespace;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.preference.SeekBarPreference;
import android.util.Log;

public class PrefActivity extends PreferenceActivity {

    private SharedPreferences mPrefs;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);

        addPreferencesFromResource(R.xml.glass_prefs);
        Preference matchTreshold = findPreference("match_treshold");
//        code doesn't compile
//        if (match_treshold instanceof SeekBarPreference){}
        Log.d("Pref", "onCreate: SeekBarClass=" + matchTreshold.getClass().getName());
        //prints 'android.preference.SeekBarPreference'
        //one cannot import android.preference.SeekBarPreference
    }
}

, вам нужно добавить

реализация 'com.android.support:preference-v7:28.0.0'

в build.gradle deps

1 Ответ

0 голосов
/ 19 декабря 2018

Объект SeekBarPreference, с которым вы заканчиваете в android.preference.PreferenceActivity, действительно android.preference.SeekBarPreference.Проблема в том, что этот класс скрыт в SDK ( source ), поэтому Android Studio не будет предлагать его для автозаполнения и не будет импортировать его автоматически.Поскольку вы используете в своем проекте библиотеки поддержки, а версия поддержки SeekBarPreference является общедоступной, это будет класс Android Studio, который будет использоваться там, поэтому возникает конфликт.

К сожалению, PreferenceActivity не проверяет, откуда идет предпочтительный XML, поэтому он с радостью создаст экземпляр этого класса платформы всякий раз, когда видит тег <SeekBarPreference>.Возможно, это ошибка, но я не уверен, что они сочтут это так, поскольку этот класс нигде не упомянут в документации.

Возможно, вы все еще можете использовать платформу SeekBarPreference, так как она должна работатькак и любой другой простой Preference, хотя он может стать немного волосатым, если вам нужно манипулировать им напрямую.Однако, как вы уже упоминали, написание своего собственного решения, безусловно, является более надежным и доступным решением.Класс платформы (ссылка выше) является довольно простым подклассом Preference, так что вы даже можете просто скопировать его в свой проект, почти как есть.Соответствующие макеты ( здесь и здесь ) аналогично просты и не полагаются на что-либо еще скрытое от SDK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...