不需要强制转换findViewById的结果?

问题描述 投票:0回答:7

最近我发现AndroidStudio提醒我删除一些类转换。我记得以前我们必须对findViewById的结果进行强制转换,但现在不需要了。

findViewById的结果仍然是View,所以我想知道为什么我们不需要强制转换类?

我找不到任何提到的文件,有人能找到任何文件吗?

android casting findviewbyid
7个回答
239
投票

从 API 26 开始,

findViewById
对其返回类型使用推理,因此您不再需要进行强制转换。

旧定义:

View findViewById(int id)

新定义:

<T extends View> T findViewById(int id)

所以如果你的

compileSdk
至少是26,这意味着你可以利用这个:)


13
投票

根据这篇文章

以下函数依赖于 Java 的泛型自动类型推断,以消除手动转换的需要:

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

12
投票

在旧版本中:

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

来自带有 SDK 26 的 Android Studio 3.0:

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

3
投票

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));

这是一个简单的改变。但对于一个经验丰富的程序员来说,这样干净的代码可以让你非常高兴,并且有助于你的编码心情:)

要执行此操作,您只需在应用程序 build.gradle 中将项目编译的 sdk 版本设置为版本 26。

您仍然可以针对早期的 sdk 版本,因此这是一个非侵入性的更改。

现在真正的问题是,如何清理一直使用强制转换的旧代码。特别是当您有数百个活动文件时。您可以手动完成,也可以聘请实习生来完成 😛。但幸运的是,对于所有这些实习生来说,Android Studio 已经准备好帮助我们解决这个问题。

当您放置插入符号(或单击冗余转换)时,Android Studio 会建议 2 个选项来处理冗余转换。

首先,它会建议删除多余的强制转换,或者您可以选择清理代码。它将删除该文件的所有冗余转换。这更好,但我们想要更多。我们不想打开每个文件并逐一进行清理。

IntelliJ idea 的特殊之处之一是一个称为“意图操作”的功能。您所要做的就是按 ctrl+shift+A,然后输入 clean。并选择代码清理操作,并选择整个项目范围。通过这几个简单的步骤,您的代码将会变得更加干净。

重要的一点是您可以使用某些代码版本控制系统来执行此操作。这样您就可以比较意图操作所做的更改并恢复您想要的任何文件。

从原帖复制:

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


2
投票

Android Studio 会提醒您删除强制转换,如果您使用 View 类中的常用属性,例如 visibility 或一些常用方法,例如 onClick()

例如:

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

在这种情况下你可以简单地写:

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

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;
}

0
投票

可以添加

viewbinding
来避免
findViewById
,查看官方
ViewBinding
文档。

© www.soinside.com 2019 - 2024. All rights reserved.