【问题标题】:No need to cast the result of findViewById?不需要转换 findViewById 的结果?
【发布时间】:2017-12-07 17:32:08
【问题描述】:

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

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

我找不到任何提到的文件,任何人都可以找到任何文件吗?

【问题讨论】:

  • 因为现在是<T extends View> T findViewById(int id) ?
  • 您需要在 View 类中不存在的任何操作的情况下进行转换,例如 ImageView 的情况,如果要使用 setImageResource,则需要将 findViewById 与 ImageView 进行转换
  • 但是如果去掉“冗余”转换,我觉得一眼就知道变量类型有点不方便。

标签: android casting findviewbyid


【解决方案1】:

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

旧定义:

View findViewById(int id)

新定义:

<T extends View> T findViewById(int id)

所以如果你的compileSdk至少是26,那就意味着你可以利用这个:)

【讨论】:

  • 如果我们移除演员表,我们的应用仍然可以在低端设备上运行,对吧?
  • @user1032613:是的,这些应用程序仍然可以在较低的设备上正常运行。
  • 如果类型错误会抛出异常吗?
  • 就像布局文件中的视图是不同类型的一样?是的,当然,它仍然是ClassCastException
  • @activity 运行时没有泛型;它只是编译时语法糖。
【解决方案2】:

据此article

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

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

【讨论】:

    【解决方案3】:

    在旧版本中:

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

    来自带有 SDK 26 的 Android Studio 3.0:

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

    【讨论】:

    • 这没有提供问题的答案。
    【解决方案4】:

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

    例如:

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

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

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

    【讨论】:

    • 你仍然需要声明类型,你必须写:findViewById(R.id.image_car).setVisibility(View.VISIBLE);
    • Android Studio 提醒我们移除显式转换,因为它在 Java 的泛型自动类型推断的实现中发生了变化 - 它与您使用的方法没有任何关系。
    【解决方案5】:

    Android 0,清理投射

    谷歌在 2017 年 IO 中宣布的一件事就是所谓的“抛弃”:)。 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。并选择 Code Clean up action,并选择整个项目范围。通过这几个简单的步骤,您的代码将变得更加简洁。

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

    从原帖复制:

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

    【讨论】:

    • 问题是why,而不是howThe result of findViewById is still View, so i want to know why we don't need to cast the class?
    • "你所要做的就是按下 ctrl+shift+A 然后输入 clean"。 “类型清洁”是什么意思?如果您从那时开始输入,您将删除整个文件
    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-31
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      相关资源
      最近更新 更多