Adapter 또는 ViewHolder의 Kotlin 합성


84

저는 kotlin을 처음 사용합니다. 클래스 findViewById에서 성가신 메서드 대신 합성 메서드를 찾아서 사용하려고 시도했지만 Activity"View (어댑터 클래스에서 유용함)에서 합성 속성을 호출하려면 kotlinx.android.synthetic.main도 가져와야합니다. .전망.*." 하지만 정확히 어떻게 작동하는지 알 수 없습니까? 예가 있습니까?


블로그 또는이 예제를
Cabezas

답변:


96

https://github.com/antoniolg/Kotlin-for-Android-Developers의 간단한 예

import kotlinx.android.synthetic.item_forecast.view.*

class ForecastListAdapter() : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        fun bindForecast(forecast: Forecast) {
            itemView.date.text = forecast.date.toDateString()
        }
    }
}

쓸 필요가 없습니다

val view = itemView.findViewById(R.id.date) as TextView
view.text = forecast.date.toDateString()

다만

itemView.date.text = forecast.date.toDateString()

간단하고 효과적입니다!


4
좋아, 이것은 멍청한 질문 일 수 있지만 'itemView'참조는 어디에서 왔습니까?
Saulo Aguiar

4
뷰 확장에 대한 캐시가 없으므로 일반 viewHolder에서와 같이 뷰에 대한 참조를 캐시해야합니다.
Miha_x64

21
: 불행하게도) (각 바인드에 findViewById를에 전화 호출되는 medium.com/proandroiddev/...을
미구엘 벨트란

2
@Mike Kotlin 1.1.4부터 모든 뷰가 캐시됩니다. ViewHolders에서도. 게시 한 기사에도이 내용이 언급되어 있습니다.
Stefan Medack 2017-10-05

2
@StefanMedack 저는이 기사의 저자입니다. :) 실험적 기능의 일부일 뿐이며 수동으로 활성화해야한다는 점을 지적해야합니다. 나는 아직 그것을 시도하지 않았습니다.
Miguel Beltran

37

Kotling 1.1.4 출력

추가 정보 : https://antonioleiva.com/kotlin-android-extensions/

다음을 build.gradle 에 추가하여 Kotlin Android 확장을 사용 설정해야합니다 .

apply plugin: 'org.jetbrains.kotlin.android.extensions'
androidExtensions {
    experimental = true
}

이 새로운 버전의 Kotlin 이후 Android 확장 프로그램은 몇 가지 새로운 흥미로운 기능을 통합했습니다. 모든 클래스의 캐시 (흥미롭게도 ViewHolder 포함)

ViewHolder (또는 사용자 정의 클래스)에서 사용. 이 클래스는 LayoutContainer인터페이스 를 구현해야합니다 .

class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), 
        LayoutContainer {

    fun bind(title: String) {
        itemTitle.text = "Hello Kotlin!"
    }
}

3
이 정보에 추가 : Kotlin 1.1.4에 따라이 기능은 실험적이며 build.gradle 파일에서 활성화해야합니다
Miguel Beltran

2
더 이상 실험적입니까? 내가 생산 코드에서 이것을 사용하려면
카슨 Holzheimer에게

@CarsonHolzheimer이 기능은 아직 실험 중입니다
the_dani dec

에서도 작동하지 않는 것 같습니다 1.3.21. 나는 그들이 그것을 구현하지 않을 것이라고 생각합니다
user924

하지만 우리는 사용할 수 containerView.itemTitle.text = "Hello Kotlin!"있고 그것으로 충분하다고 생각합니다
user924

11

당신은 필요합니다

import kotlinx.android.synthetic.row_wall.view.*

그리고 나중에 다음과 같은 내용이 있습니다.

convertView.titleText.text = item.title

요점은 view. *가 View 클래스에 대한 확장을 도입한다는 것입니다.


1
대답은 이미 주어졌습니다. stackoverflow.com/a/33428208/7767664 왜 그것을 반복 했습니까?
user924

8

시험

class CustomViewModel(val baseView: View) {
    val firstName = baseView.firstName
    val lastName = baseView.lastName
}

뷰 객체는 뷰 참조를 노출합니다 : https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890


대답은 이미 주어졌습니다. stackoverflow.com/a/33428208/7767664 왜 그것을 반복 했습니까?
user924

@ user924. 답변이 이미 다른 스레드에있는 경우 검토하고 현재 스레드를 중복으로 표시하고 다른 스레드에 대한 참조를 추가하십시오
hyena

4

최신 버전 l ;.을 사용하는 경우 실험적 = true를 추가 할 필요가 없습니다.

프로젝트 수준 Gradle

classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21'

그리고 앱 수준 Gradle에서

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //These should be on the top of file.

그리고 의존성 ..

implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'

아래로 가져 오기

import kotlinx.android.synthetic.main.your_layout_file_name.view.*

및 예

import kotlinx.android.synthetic.main.item_animal.view.*

class AnimalVH(parent: ViewGroup, layoutID: Int) : BaseViewHolder<Animal>(parent, layoutID) {

    override fun bindData(animal: Animal) {
        itemView.tv_animal.text = animal.title
    }
}

BaseViewHolder는

abstract class BaseViewHolder<T>(parent: ViewGroup, layoutID: Int) : RecyclerView.ViewHolder(
    LayoutInflater.from(parent.context).inflate(layoutID, parent, false)
) {
    abstract fun bindData(model: T)
}

이것에 대한 공식적인 확인이 있습니까? 내가 사용 믿는다 .view.*대체가하는 것, 수입이 목적을 패배 findViewById<>때마다, - 아주 패턴 ViewHolder에서 dissuades.
Skynet


1

이는 소스 파일의 시작 부분에 다음 줄을 배치해야 함을 의미합니다.

import kotlinx.android.synthetic.main.view.*

그래서 지금 대신에, 예를 들어, findView(R.id.textView) as TextView당신은 작성합니다 textView. 후자는 패키지에있는 합성 확장 속성 kotlinx.android.synthetic.main.view이므로 모든 것을 가져와야합니다.

있습니다 공식 사이트에 튜토리얼 을 살펴.


1
나는 그것을 아직 보았다. 위에서 설명한 것처럼 내 활동을 위해 수행했습니다. 그러나 BaseAdapter 파생물 내에서 어떻게 사용할 수 있습니까?
busylee

1
글쎄, 기본적으로 , 같은 findViewById()에서 메서드를 호출 할 수 있습니다 . Kotlin Android 확장 프로그램을 사용하면 . 이 코드가 함수 내부에 작성 Viewholder.findViewById(R.id.name)holder.namegetView()val base = inflater.inflate(R.layout.list_item, parent, false) base.name.text = "John Smith"
되었다고

하지만 레이아웃이 다양한 뷰 홀더를 여러 개 사용해야한다면 어떻게하나요? 합성으로 어떻게 실현할 수 있습니까? 각 레이아웃에 대해 특정 "합성 링크"를 사용해야하고 유사한 ID를 가진 여러 레이아웃이 있기 때문입니다.
Natan Rubinstein

0

참고 : 뷰 조회를 위해 합성보다 데이터 바인딩이 권장됩니다.

Reddit의 Google 에서 Android 용 DA의 댓글

야! 여기 Google에서 Android 용 개발자 옹호자!

여기에 약간의 배경을 추가하고 싶었습니다. 합성 뷰가있는 Kotlin 확장 프로그램은 사용하지 않도록 권장해서는 안되지만 의도적으로 '권장'되지 않았습니다. 그들이 당신을 위해 일하고 있다면 당신의 앱에서 계속 사용하십시오!

잘못된 조회에 대한 검사없이 실제로 부풀려진 레이아웃과 관련이없는 ID의 글로벌 네임 스페이스를 노출하고 Kotlin 전용이며 뷰가 일부 구성에만있는 경우 null 허용 여부를 노출하지 않습니다. 이러한 문제로 인해 API가 Android 앱의 비정상 종료 횟수를 증가시킵니다.

반면에보기 조회를 단순화하는 데 도움이되는 경량 API를 제공합니다. 이 공간에서는 데이터 변경에 따라 뷰를 자동으로 업데이트하기 위해 LiveData와 통합 할뿐만 아니라 자동 뷰 조회도 수행하는 데이터 바인딩을 살펴볼 가치가 있습니다.

오늘날이 공간에는 몇 가지 옵션이 있습니다.

데이터 결합은보기 조회 및 결합에 대한 권장 사항이지만 Android Kotlin 확장 프로그램과 비교할 때 약간의 오버 헤드를 추가합니다. 이것이 여러분의 앱에 적합한 지 살펴볼 가치가 있습니다. 또한 데이터 바인딩을 사용하면 LiveData를 관찰하여 데이터가 변경 될 때 뷰를 자동으로 바인딩 할 수 있습니다. Kotlin Extensions와 비교하여 뷰 조회 및 유형 안전성에 대한 컴파일 시간 검사를 추가합니다. Android Kotlin 확장 프로그램은 공식적으로 권장되지 않습니다 (권장 사항과 동일하지 않음). 위에서 언급 한 문제와 함께 제공되므로 코드에서는 사용하지 않습니다. Butter Knife는 Kotlin과 Java 프로그래밍 언어 모두에서 작동하는 매우 인기있는 또 다른 솔루션입니다. 여기에 댓글을 읽고 Kotlin Extensions에 큰 행운을 빕니다. 훌륭합니다. API를 지속적으로 개선하는 방법을 모색 할 때 염두에 두어야 할 사항입니다. 데이터 바인딩을 살펴 보지 않았다면 확실히 시도해보십시오.

제쳐두고, 내부 코드 스타일 가이드는 코드베이스 외부에서 직접 적용 할 수 없습니다. 예를 들어 mPrefixVariables를 사용하지만 모든 앱이 해당 스타일을 따라야 할 이유는 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.