findViewByIdの結果をキャストする必要はありませんか?


152

最近、AndroidStudioからクラスキャストを削除するように通知されていることがわかりました。昔はfindViewByIdの結果をキャストする必要があったのを覚えていますが、今は必要ありません。

findViewByIdの結果は引き続きViewなので、クラスをキャストする必要がない理由を知りたいですか?

言及されているドキュメントが見つかりません。ドキュメントは見つかりますか?


7
それは今<T extends View> T findViewById(int id)ですか?
セルビン2017

ImageViewの場合のように、Viewクラスにない操作の場合はキャストする必要があります。setImageResourceを使用する場合は、ImageViewでfindViewByIdをキャストする必要があります
Gagan Deep

しかし、「冗長な」キャストを削除すると、変数の型が一目でわかるので少し不便に感じます。
Fruit

回答:


235

API 26以降findViewById、戻り値の型に推論を使用するため、キャストする必要がなくなりました。

古い定義:

View findViewById(int id)

新しい定義:

<T extends View> T findViewById(int id)

つまり、compileSdk26以上の場合は、これを利用できるということです。


ありがとう、そして別の質問。SDKマネージャーでsdk26のソースが見つからないので、この新しい定義はどこにありますか?
Eric Zhao

17
キャストを削除しても、アプリは下位のデバイスで実行できますよね?
user1032613 2017年

17
@ user1032613:はい、アプリは問題なく下位のデバイスでも動作します。
Alireza Noorali 2017

1
タイプが間違っていると、例外がスローされますか?
fobbymaster 2018

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

SDK 26を搭載したAndroid Studio 3.0から:

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

16
これは質問の答えを提供しません。
Wijay Sharma

1

Android Studioは、可視性onClick()などのいくつかの一般的なメソッドなど、Viewクラスの一般的な属性を使用する場合、キャストを削除するように通知します

例えば:

((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 2017年

Android Studioは、Javaのジェネリック自動型推論の実装で変更されているため、明示的なキャストを削除するように通知します。使用しているメソッドとは何の関係もありません。
zeroDivider

1

Android 0、キャストをクリーンアップ

GoogleがIO 2017で発表するものの1つは、「キャストアウェイ」と呼ばれるものです。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バージョンをアプリのbuild.gradleでバージョン26に設定するだけで済みます。

以前のsdkバージョンも対象とすることができるため、煩わしい変更ではありません。

さて、本当の問題は、これまでずっとキャストを使用していた古いコードをどのようにクリーンアップするかです。特に、何百ものアクティビティファイルがある場合。手動で行うことも、インターンを雇って行うこともできます😛。しかし、幸運なことに、これらすべてのインターンにとって、アンドロイドスタジオはすでにこれを支援する準備をしています。

キャレットを配置すると(または冗長キャスティングをクリックすると)、Android Studioは冗長キャスティングを処理する2つのオプションを提案します。

最初に、冗長なキャストを削除するか、クリーンアップコードを選択することをお勧めします。そのファイルのすべての冗長キャストが削除されます。これは良いですが、もっと欲しいです。各ファイルを開きたくないので、これを1つずつクリーンアップします。

IntelliJのアイデアを特別なものにしていることの1つは、インテントアクションと呼ばれる機能です。Ctrl + Shift + Aを押してから、cleanと入力するだけです。コードのクリーンアップアクションを選択し、プロジェクトスコープ全体を選択します。このいくつかの簡単な手順で、コードはずっときれいになります。

重要なポイントの1つは、これをいくつかのコードバージョン管理システムで行うことです。このようにして、インテントアクションによって行われた変更を比較し、必要なファイルを元に戻すことができます。

元の投稿からコピー:

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


1
質問はだったwhy、ではないhowThe result of findViewById is still View, so i want to know why we don't need to cast the class?
zeroDivider

「ctrl + shift + Aを押してから、cleanと入力するだけです」。「タイプクリーン」とはどういう意味ですか?その時点で入力を開始すると、ファイル全体が消去されます
Stealth Rabbi

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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.