Не потрібно приводити результат findViewById?


152

Нещодавно я виявив, що AndroidStudio нагадує мені видалити акторський склад. Я пам’ятаю, що за старих часів ми мусимо виводити результат findViewById, але зараз це не потрібно.

Результатом findViewById все ще є Перегляд, тому я хочу знати, чому нам не потрібно видавати клас?

Я не можу знайти жодних згаданих документів, чи може хтось знайти якийсь документ?


7
бо тепер це <T extends View> T findViewById(int id)?
Селвін

вам потрібен кастинг у разі будь-якої операції, якої немає в класі View, як, наприклад, у випадку ImageView. Якщо ви хочете використовувати setImageResource, тоді вам потрібно передати FindViewById з ImageView
Gagan Deep

Але мені здається трохи незручним, щоб знати тип змінної з першого погляду, якби видалити "зайвий" кастинг.
фрукти

Відповіді:


235

Починаючи з API 26, findViewByIdвикористовує умовивід для свого типу повернення, тому вам більше не доведеться робити трансляцію.

Старе визначення:

View findViewById(int id)

Нове визначення:

<T extends View> T findViewById(int id)

Отже, якщо ваших compileSdkпринаймні 26, це означає, що ви можете скористатися цим :)


Дякую і ще одне питання. я не можу знайти джерела для sdk26 у менеджері sdk, тож де я можу знайти це нове визначення, будь ласка?
Ерік Чжао

17
Якщо ми видалимо команду, наші додатки все ще можуть працювати на нижчих пристроях, правда?
користувач1032613

17
@ user1032613: Так, програми все ще можуть працювати на нижчих пристроях без проблем.
Аліреза Нооралі

1
Чи викине це виняток, якщо це неправильний тип?
fobbymaster

1
Як у випадку, якщо вигляд у файлі макета іншого типу? Так, звичайно, все одно це було б ClassCastException.
Едуард Б.

13

Відповідно до цієї статті :

Наступна функція покладається на автоматичний висновок загального типу Java для того, щоб уникнути необхідності введення вручну:

protected <T extends View> T findViewById(@IdRes int id) {
    return (T) getRootView().findViewById(id);
}

11

У старих версіях:

AutoCompleteTextView name = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);

Від Android Studio 3.0 із SDK 26:

AutoCompleteTextView name = findViewById(R.id.autoCompleteTextView);

16
Це не дає відповіді на запитання.
Wijay Sharma

1

Android Studio нагадує видалити кастинг, якщо ви використовуєте загальні атрибути з класу View , як-от видимість або деякі поширені методи, наприклад, onClick ()

Наприклад:

((ImageView) findViewById(R.id.image_car)).setVisibility(View.VISIBLE);

У цьому випадку ви можете просто написати:

findViewById(R.id.image_car).setVisibility(View.VISIBLE);

2
вам все одно доведеться оголосити тип, вам доведеться написати: findViewById <ImageView> (R.id.image_car) .setVisibility (View.VISIBLE);
Slickelito

Android Studio нагадує нам видалити явний кастинг, оскільки він змінився при впровадженні загального автоматичного виводу Java на загальну мову - це не має нічого спільного з тим, який метод ви використовуєте.
zeroDivider

1

Android 0, очищення кастингу

Одна з речей, яку Google оголошує в IO 2017 - це те, що називається "відкинутий" :). Розробнику Android не потрібно робити кастинг вручну для FindViewById (). Наприклад, старий спосіб отримати перегляд тексту за допомогою findViewById () був би приблизно таким.

TextView txtDesc = (TextView) findViewById(R.id.textViewDesc);
txtDesc.setText(getString(R.string.info_angkot_description));

Тоді як новий спосіб був би таким

TextView txtDesc = findViewById(R.id.textViewDesc);
txtDesc.setText(getString(R.string.info_angkot_description));

Це проста зміна. Але для досвідченого програміста чистий код на зразок цього може зробити вас дуже щасливим, і це допоможе в настрої кодування :)

Щоб зробити це, вам потрібно було лише встановити компільовану версію SDK для вашого проекту на версію 26 у вашому додатку build.gradle.

Ви все ще можете націлити на попередню версію sdk, тому це не нав'язливі зміни.

Тепер справжня проблема, як ви очистите той старий код, який використовує кастинг весь цей час. Особливо, коли вам подобаються сотні файлів активності. Ви можете це зробити вручну, або, можливо, найняли стажиста для цього 😛. Але, на щастя, для всіх цих стажерів, андроїд-студія вже готова допомогти нам у цьому.

Коли ви покладете свою карету (або натисніть на надлишковий кастинг), андроїд-студія запропонує 2 варіанти обробляти надлишковий кастинг.

Спочатку він запропонує видалити цей надлишковий склад, або ви можете вибрати очистити код. Це видалить увесь зайвий склад для цього файлу. Це краще, але ми хочемо більше. Ми не хочемо відкривати кожен файл і робити це очищення по одному.

Однією з речей, які роблять IntelliJ ідеєю Особливою, є те, що функція називається наміром дії. Все, що вам потрібно зробити, це натиснути клавішу ctrl + shift + A, а потім набрати очищення. І виберіть дію «Очищення коду» та виберіть весь обсяг проекту. З допомогою цих декількох простих кроків ваш код буде набагато чистішим.

Важливим моментом є те, що ви робите це з деякою системою версії коду. Таким чином ви можете порівняти зміни, які були внесені в результаті наміру, та відновити будь-які потрібні файли.

Скопійовано з оригінальної публікації:

https://medium.com/@abangkis/android-0-clean-up-casting-c30acec56cef


1
питання було why, а не how:The result of findViewById is still View, so i want to know why we don't need to cast the class?
zeroDivider

"Все, що вам потрібно зробити, це натиснути клавішу ctrl + shift + A, а потім набрати". Що ви маєте на увазі під "типом чистого"? Якщо ви почнете набирати текст із цього моменту, ви стерте весь файл
Стелс Раббі

0

У вихідному коді ViewGroupє вміст аргументу повернення. Тож не потрібно повторювати:

@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
    if (id == NO_ID) {
        return null;
    }
    return findViewTraversal(id);
}

@Override
protected <T extends View> T findViewTraversal(@IdRes int id) {
    if (id == mID) {
        return (T) this;  //###### cast to T
    }

    final View[] where = mChildren;
    final int len = mChildrenCount;

    for (int i = 0; i < len; i++) {
        View v = where[i];

        if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
            v = v.findViewById(id);

            if (v != null) {
                return (T) v; //###### cast to T
            }
        }
    }

    return null;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.