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

最近我发现 AndroidStudio 提醒我删除一些类强制转换。我记得在过去,我们必须强制转换 findViewById 的结果,但是现在没有必要了。

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

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

50439 次浏览

从 API 26开始,findViewById对其返回类型使用推断,因此不再需要强制转换。

老定义:

View findViewById(int id)

新定义:

<T extends View> T findViewById(int id)

因此,如果你的 compileSdk至少是26,这意味着你可以利用这一点:)

如果您使用来自 观景类的公共属性(如 能见度)或一些公共方法(如 OnClick ()) ,Android Studio 提醒您删除强制转换

例如:

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

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

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

在旧版本中:

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

来自 Android Studio 3.0和 SDK 26:

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

根据 文章:

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

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

安卓0号,清理选角

谷歌在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));

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

要做到这一点,您只需要在 app build.gradle 中将项目编译的 sdk 版本设置为26版。

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

现在真正的问题是,如何清除一直使用强制转换的旧代码。特别是当你有上百个活动文件的时候。你可以手动操作,或者雇一个实习生来做。但幸运的是,所有的实习生,机器人工作室已经准备帮助我们这一点。

当你把你的插入符号(或点击多余的铸造)安卓工作室将建议2选项来处理多余的铸造。

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

使得 IntelliJ 思想特别的一件事情是一个被称为意图行为的特性。你所要做的就是按下 ctrl + shift + A,然后键入 clean。并选择“代码清理”操作,然后选择整个项目范围。通过这几个简单的步骤,您的代码将变得更加干净。

一个重要的问题是,您可以使用一些代码版本控制系统来实现这一点。通过这种方式,您可以比较意图操作所做的更改,并恢复所需的任何文件。

复印件原件:

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

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