代码之家  ›  专栏  ›  技术社区  ›  Rafael T

android.support如何打破Javas类型安全?

  •  1
  • Rafael T  · 技术社区  · 7 年前

    今天我遇到了一个非常奇怪的行为。我知道,我使用的是不推荐的API,但据我所知,这是不可能的。

    我有一个 android.preference.PreferenceActivity 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 类(该类 Seekbarp参考 不是)。

    但此代码返回一个有效的Pref:

     Preference match_treshold = findPreference("match_treshold");
    

    我不允许投:

     if (match_treshold instanceof SeekBarPreference){}
    

    错误:不兼容的类型:首选项无法转换为SeekBarPreference

    但令人惊讶的是,如果我调试代码,我会得到这样的结果 Debugging SeekBarPreference

    android.preference.SeekbarPreference . 如果我用谷歌搜索,我能找到的就是 https://developer.android.com/reference/android/support/v7/preference/SeekBarPreference

    这说明它是基于 android.preference.SeekBarPreference

    在我看来,除了糟糕的设计决策之外,不继承Android的support.v7首选项:这到底是怎么回事?

    编辑: 由于请求,我发布了活动类

    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 回复  |  直到 7 年前
        1
  •  1
  •   Mike M.    7 年前

    这个 SeekBarPreference android.preference.PreferenceActivity 确实是一个 android.preference.SeekBarPreference . 这里的问题是该类隐藏在SDK中( source Seekbarp参考

    PreferenceActivity 不检查首选项XML来自何处,因此只要看到 <SeekBarPreference> 标签这可能是一个错误,但我不确定他们会这样认为,因为该类在文档中没有提及。

    你可能仍然可以使用这个平台 ,因为它应该像其他任何基本功能一样工作 Preference ,但如果需要直接操纵它,它可能会有点毛茸茸的。然而,正如您所提到的,编写您自己的解决方案肯定是一个更可靠、更容易获得的解决方案。平台类(链接在上面)是一个相当简单的 偏爱 子类,所以您甚至可以将其复制到项目中,几乎原样。相关布局( here here )同样简单,不依赖SDK中隐藏的任何其他内容。

    推荐文章