findViewById의 결과를 캐스트 할 필요가 없습니까?


152

최근에 AndroidStudio가 클래스 캐스트를 제거하도록 상기시키는 것을 발견했습니다. 예전에는 findViewById의 결과를 캐스트해야하지만 이제는 필요하지 않습니다.

findViewById의 결과는 여전히 View이므로 클래스를 캐스팅 할 필요가없는 이유를 알고 싶습니다.

언급 된 문서를 찾을 수 없습니다. 누구든지 문서를 찾을 수 있습니까?


7
지금 이니까 <T extends View> T findViewById(int id)?
Selvin

당신은 당신이 setImageResource를 사용하려는 경우, 이미지 뷰의 경우처럼,보기 클래스가없는 모든 작업의 경우에는 주조 필요, 당신은 캐스트에 이미지 뷰와 findViewById를 필요
가갠 깊은

그러나 "중복"캐스팅을 제거하면 변수 유형을 한눈에 알기가 다소 불편합니다.
과일

답변:


235

API 26부터는 findViewById리턴 유형에 추론을 사용하므로 더 이상 캐스트 할 필요가 없습니다.

오래된 정의 :

View findViewById(int id)

새로운 정의 :

<T extends View> T findViewById(int id)

따라서 귀하의 compileSdk26 세 이상인 경우, 귀하 가 이것을 사용할 수 있음을 의미합니다. :)


고마워, 또 다른 질문. SDK 관리자에서 SDK26의 소스를 찾을 수 없으므로이 새로운 정의를 어디에서 찾을 수 있습니까?
Eric Zhao

17
전송을 제거해도 앱이 더 낮은 기기에서 계속 실행될 수 있습니다.
user1032613

17
@ user1032613 : 예, 응용 프로그램은 문제없이 여전히 낮은 장치에서 작동 할 수 있습니다
Alireza Noorali

1
잘못된 유형 인 경우 예외가 발생합니까?
fobbymaster

1
레이아웃 파일의보기가 다른 유형 인 것처럼? 예, 물론 여전히 그렇습니다 ClassCastException.
에두아르 B.

13

기사 에 따르면 :

다음 함수는 수동 캐스팅이 필요하지 않도록 Java의 generics 자동 유형 유추에 의존합니다.

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

Android Studio는 Java의 제네릭 자동 형식 유추 구현에서 변경 되었기 때문에 명시 적 캐스팅을 제거하도록 상기시켜줍니다. 사용중인 메소드와는 아무런 관련이 없습니다.
zeroDivider

1

안드로이드 0, 캐스팅 정리

구글이 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));

간단한 변화입니다. 그러나 노련한 프로그래머의 경우 이와 같은 깨끗한 코드를 사용하면 매우 행복하고 코딩 분위기에 도움이 될 수 있습니다. :)

이를 위해서는 app build.gradle에서 프로젝트 컴파일 sdk 버전을 버전 26으로 설정하기 만하면됩니다.

이전 SDK 버전도 계속 타겟팅 할 수 있으므로 방해가되지 않는 변경 사항입니다.

이제 진짜 문제는, 이번에 캐스팅을 사용하는 오래된 코드를 어떻게 정리합니까? 특히 수백 개의 활동 파일이있는 경우. 수동으로 할 수도 있고 인턴을 고용하여 할 수도 있습니다. 그러나 운 좋게도 모든 인턴 인 안드로이드 스튜디오는 이미 우리를 도울 준비를했습니다.

캐럿을 넣거나 중복 캐스팅을 클릭하면 android studio에서 중복 캐스팅을 처리하는 두 가지 옵션을 제안합니다.

먼저 중복 캐스트를 제거하거나 정리 코드를 선택할 수 있습니다. 해당 파일에 대한 모든 중복 캐스트를 제거합니다. 이것은 더 좋지만 더 많이 원합니다. 우리는 각 파일을 열고 싶지 않아 하나씩 정리합니다.

IntelliJ idea를 특별하게 만드는 것 중 하나는 인 텐트 액션이라는 기능입니다. ctrl + shift + A를 누른 다음 clean을 입력하기 만하면됩니다. 코드 정리 조치를 선택하고 전체 프로젝트 범위를 선택하십시오. 이 몇 가지 간단한 단계만으로 코드가 훨씬 깨끗해집니다.

한 가지 중요한 점은 일부 코드 버전 관리 시스템에서이 작업을 수행한다는 것입니다. 이렇게하면 의도 조치에 의해 수행 된 변경 사항을 비교하고 원하는 파일을 되돌릴 수 있습니다.

원본 게시물에서 복사 :

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 16:24에

"Ctrl + Shift + A를 누른 다음 clean을 입력하기 만하면됩니다." "type 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.