Kotlin tổng hợp trong Bộ điều hợp hoặc ViewHolder


84

Tôi là người mới trong kotlin. Tôi đã tìm và cố gắng sử dụng phương thức tổng hợp thay vì phương thức gây phiền nhiễu findViewByIdtrong Activitylớp của mình , nhưng tôi nhận thấy "Nếu chúng ta muốn gọi các thuộc tính tổng hợp trên View (hữu ích trong các lớp bộ điều hợp), chúng ta cũng nên nhập kotlinx.android.synthetic.main .lượt xem.*." Nhưng tôi không thể tìm ra cách nó hoạt động chính xác? Có ví dụ nào không?


Bạn có thể kiểm tra blog này hoặc ví dụ
Cabezas,

Câu trả lời:


96

Ví dụ đơn giản từ 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()
        }
    }
}

Không cần viết

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

Chỉ

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

Đơn giản và hiệu quả!


4
được rồi, đây có thể là một câu hỏi ngớ ngẩn, nhưng tham chiếu 'itemView' đến từ đâu?
Saulo Aguiar

4
Không có bộ nhớ cache cho các tiện ích mở rộng chế độ xem, vì vậy các tham chiếu đến các chế độ xem phải được lưu vào bộ nhớ đệm, giống như trong viewHolder thông thường.
Miha_x64

21
may mà đang kêu gọi để findViewById trên mỗi bind () gọi: medium.com/proandroiddev/...
Miguel Beltran

2
@Mike kể từ Kotlin 1.1.4, tất cả các lượt xem sẽ được lưu vào bộ nhớ đệm. Ngay cả trong ViewHolders. Bài báo bạn đã đăng cũng đề cập đến điều này.
Stefan Medack

2
@StefanMedack Tôi là tác giả của bài viết :) Mặc dù tôi phải chỉ ra rằng nó chỉ là một phần của các tính năng thử nghiệm và cần được kích hoạt theo cách thủ công. Tôi vẫn chưa thử nó.
Miguel Beltran

37

Kotling 1.1.4 ra

Thông tin thêm: https://antonioleiva.com/kotlin-android-extensions/

Bạn cần kích hoạt Kotlin Android Extentions bằng cách thêm nó vào build.gradle:

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

Kể từ phiên bản Kotlin mới này, Tiện ích mở rộng Android đã kết hợp một số tính năng thú vị mới: bộ nhớ đệm trong bất kỳ lớp nào (thú vị là bao gồm cả ViewHolder)

Sử dụng nó trên ViewHolder (hoặc bất kỳ lớp tùy chỉnh nào). Lưu ý rằng lớp này nên triển khai LayoutContainergiao diện:

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

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

3
Thêm vào thông tin này: Theo Kotlin 1.1.4 tính năng là thực nghiệm và cần phải được kích hoạt trên các tập tin build.gradle
Miguel Beltran

2
Thử nghiệm này còn nữa không? Tôi muốn sử dụng cái này trong mã sản xuất
Carson Holzheimer,

@CarsonHolzheimer tính năng này vẫn đang trong giai đoạn thử nghiệm
the_dani 15/12/18

có vẻ như nó thậm chí không hoạt động với 1.3.21. Tôi nghĩ rằng họ sẽ không thực hiện nó
user924

nhưng chúng ta có thể sử dụng containerView.itemTitle.text = "Hello Kotlin!"và tôi nghĩ rằng đó là đủ
user924

11

Bạn cần

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

Và sau đó là một cái gì đó dọc theo dòng:

convertView.titleText.text = item.title

Vấn đề là khung nhìn. * Giới thiệu các phần mở rộng cho lớp View.


1
câu trả lời đã được đưa ra stackoverflow.com/a/33428208/7767664 tại sao bạn lặp lại nó?
user924, 26/02/19

8

Thử

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

Đối tượng xem hiển thị các chế độ xem ref: https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890


câu trả lời đã được đưa ra stackoverflow.com/a/33428208/7767664 tại sao bạn lặp lại nó?
user924,

@ người dùng924. nếu câu trả lời đã có trong một chủ đề khác, vui lòng kiểm duyệt và đánh dấu chủ đề hiện tại là trùng lặp và thêm tham chiếu vào chủ đề khác
hyena

4

Nếu bạn đang sử dụng phiên bản mới nhất l;. Bạn không cần phải thêm thử nghiệm = true vào nó.

trong Gradle cấp dự án

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

Và trong Gradle cấp ứng dụng

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

và trong các phần phụ thuộc ..

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

và nhập bên dưới dưới dạng

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

và ví dụ

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 ở đâu

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

Có xác nhận chính thức nào về điều này không? Tôi tin rằng việc sử dụng .view.*nhập khẩu sẽ đánh bại mục đích findViewById<>, mỗi lần sẽ có dự phòng - chính là mô hình ViewHolderkhông được chấp nhận.
Skynet

Giải thích tại: proandroiddev.com/…
Skynet

1

Có nghĩa là bạn phải đặt dòng này ở đầu tệp nguồn của mình:

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

Vì vậy, bây giờ thay vì, chẳng hạn, findView(R.id.textView) as TextViewbạn sẽ chỉ viết textView. Sau đó là một thuộc tính tiện ích mở rộng tổng hợp nằm trong gói kotlinx.android.synthetic.main.view, đó là lý do tại sao bạn phải nhập mọi thứ từ nó.

Có một hướng dẫn trên trang web chính thức , hãy xem.


1
Tôi đã thấy nó được nêu ra. Tôi đã làm điều đó cho hoạt động của mình, như tôi đã mô tả ở trên. Nhưng làm thế nào tôi có thể sử dụng nó bên trong các dẫn xuất BaseAdapter?
busylee

1
Về cơ bản, bạn có thể gọi findViewById()phương thức trên một View, như holder.findViewById(R.id.name). Với Kotlin Android Extensions, bạn có thể viết holder.name. Giả sử mã này được viết bên trong một getView()hàm:val base = inflater.inflate(R.layout.list_item, parent, false) base.name.text = "John Smith"
yanex

Nhưng điều gì sẽ xảy ra nếu tôi phải sử dụng nhiều trình giữ chế độ xem với nhiều bố cục khác nhau? Làm thế nào tôi có thể nhận ra nó với tổng hợp? Bởi vì chúng tôi phải sử dụng "liên kết tổng hợp" cụ thể cho từng bố cục và tôi có một số bố cục có id tương tự.
Natan Rubinstein

0

FYI: Liên kết dữ liệu được khuyến nghị hơn là tổng hợp để tra cứu chế độ xem.

Nhận xét từ DA dành cho Android từ Google trên Reddit

Chào! Người ủng hộ nhà phát triển cho Android tại Google tại đây!

Tôi muốn thêm một chút nền ở đây. Tiện ích mở rộng Kotlin với các chế độ xem tổng hợp không bao giờ được “khuyến nghị” một cách cố ý mặc dù điều đó không nên được coi là khuyến nghị không sử dụng chúng. Nếu chúng làm việc cho bạn, vui lòng tiếp tục sử dụng chúng trong ứng dụng của bạn!

Chúng tôi đã tránh xa chúng (ví dụ: chúng tôi không dạy chúng trong khóa học Udacity) vì chúng để lộ không gian tên toàn cầu gồm các id không liên quan đến bố cục thực sự bị thổi phồng mà không có kiểm tra chống lại các tra cứu không hợp lệ, chỉ là Kotlin và không 't để lộ khả năng vô hiệu khi các chế độ xem chỉ có trong một số cấu hình. Tất cả cùng nhau, những vấn đề này khiến API làm tăng số lượng sự cố cho các ứng dụng Android.

Mặt khác, họ cung cấp một API nhẹ có thể giúp đơn giản hóa việc tra cứu chế độ xem. Trong không gian này, bạn cũng nên xem Data Binding, tính năng này cũng thực hiện tra cứu chế độ xem tự động - cũng như tích hợp với LiveData để tự động cập nhật chế độ xem của bạn khi dữ liệu thay đổi.

Ngày nay, có một số tùy chọn trong không gian này hoạt động:

Data Binding là khuyến nghị cho việc tra cứu chế độ xem cũng như ràng buộc, nhưng nó có thêm một chút chi phí khi so sánh với Android Kotlin Extensions. Bạn nên xem xét liệu điều này có phù hợp với ứng dụng của bạn hay không. Data Binding cũng cho phép bạn quan sát LiveData để ràng buộc các lượt xem tự động khi dữ liệu thay đổi. So với Tiện ích mở rộng Kotlin, nó bổ sung thêm tính năng kiểm tra thời gian biên dịch của tra cứu chế độ xem và an toàn kiểu. Tiện ích mở rộng Android Kotlin không được khuyến nghị chính thức (không giống như khuyến nghị chống lại). Nó đi kèm với các vấn đề được đề cập ở trên, vì vậy đối với mã của chúng tôi, chúng tôi không sử dụng chúng. Butter Knife là một giải pháp khác cực kỳ phổ biến và hoạt động cho cả Kotlin và Ngôn ngữ lập trình Java. Đọc qua các bình luận ở đây ' rất nhiều nhà phát triển đang gặp may mắn với Tiện ích mở rộng Kotlin. Điều đó thật tuyệt - và một điều chúng tôi sẽ ghi nhớ khi xem xét các cách tiếp tục cải thiện API của mình. Nếu bạn chưa xem qua Data Binding, chắc chắn hãy thử.

Ngoài ra, hướng dẫn kiểu mã nội bộ của chúng tôi không nhằm mục đích áp dụng trực tiếp bên ngoài cơ sở mã của chúng tôi. Ví dụ: chúng tôi sử dụng mPrefixVariables, nhưng không có lý do gì mà mọi ứng dụng phải tuân theo phong cách đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.