"Tidak cukup informasi untuk menyimpulkan parameter T" dengan Kotlin dan Android

110

Saya mencoba mereplikasi ListView berikut di aplikasi Android saya menggunakan Kotlin: https://github.com/bidrohi/KotlinListView .

Sayangnya, saya mendapatkan kesalahan yang tidak dapat saya atasi sendiri. Ini kode saya:

MainActivity.kt:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val listView = findViewById(R.id.list) as ListView
    listView.adapter = ListExampleAdapter(this)
}

private class ListExampleAdapter(context: Context) : BaseAdapter() {
    internal var sList = arrayOf("Eins", "Zwei", "Drei")
    private  val mInflator: LayoutInflater

    init {
        this.mInflator = LayoutInflater.from(context)
    }

    override fun getCount(): Int {
        return sList.size
    }

    override fun getItem(position: Int): Any {
        return sList[position]
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
        val view: View?
        val vh: ListRowHolder

        if(convertView == null) {
            view = this.mInflator.inflate(R.layout.list_row, parent, false)
            vh = ListRowHolder(view)
            view.tag = vh
        } else {
            view = convertView
            vh = view.tag as ListRowHolder
        }

        vh.label.text = sList[position]
        return view
    }
}

private class ListRowHolder(row: View?) {
    public val label: TextView

    init {
        this.label = row?.findViewById(R.id.label) as TextView
    }
}
}

Layoutnya persis seperti di sini: https://github.com/bidrohi/KotlinListView/tree/master/app/src/main/res/layout

Pesan kesalahan lengkap yang saya dapatkan adalah ini: Kesalahan: (92, 31) Jenis inferensi gagal: Tidak cukup informasi untuk menyimpulkan parameter T dalam fun findViewById (p0: Int): T! Harap sebutkan secara eksplisit.

Saya menghargai bantuan yang bisa saya dapatkan.

Timo Güntner
sumber
2
Dapatkah Anda mencoba mengubah this.label = ... as TextViewke this.label = row?.findViewById<TextView>dan melakukannya secara analog val listView = ...? Tolong beri tahu saya jika ini berfungsi sehingga saya dapat membuat ini jawaban yang tepat dalam kasus itu.
Christian Brüggemann
1
Baris mana yang menyebabkan kesalahan?
voddan
Dapatkah Anda mendemonstrasikan masalah dengan contoh yang lebih kecil?
voddan
@ ChristianBrüggemann Seperti ini: i.imgur.com/ZeWKjt5.png dan ini: i.imgur.com/Can7w0p.png ? Dengan hasil edit Anda sekarang ada kesalahan berikut: i.imgur.com/qqPAjrL.png
Timo Güntner
1
Coba this.label = row? .FindViewById <TextView> (R.id.label) sebagai TextView
Alf Moh

Jawaban:

224

Anda harus menggunakan API level 26 (atau lebih tinggi). Versi ini telah mengubah tanda tangan View.findViewById()- lihat di sini https://developer.android.com/about/versions/oreo/android-8.0-changes#fvbi-signature

Jadi dalam kasus Anda, di mana hasil dari findViewByIdambigu, Anda perlu memberikan tipe:

1 / Ubah

val listView = findViewById(R.id.list) as ListView untuk

val listView = findViewById<ListView>(R.id.list)

2 / Ubah

this.label = row?.findViewById(R.id.label) as TextView untuk

this.label = row?.findViewById<TextView>(R.id.label) as TextView

Perhatikan bahwa di 2 / cast hanya diperlukan karena rownullable. Jika label juga nullable, atau jika Anda menjadikannya rowtidak null, tidak akan diperlukan.

nmw
sumber
10
Berikut adalah cara untuk memecahkan masalah ini: Buka dialog Replace in Path (Ctrl + Shift + R) dan centang kotak regex. Ganti findViewById\((.+?)\)\s+as\s+(.+)dengan findViewById<$2>\($1\)dan jalankan ganti pada semua file. Itu memecahkan hampir semua kesalahan saya.
Gustav Karlsson
1
Mengapa di Java cukup untuk menyimpulkan jenis View secara default dan tidak cukup di Kotlin? findViewById(R.id.tabLayout).setOnClickListener(v-> Log.d(TAG, "login: "));ini OK untuk Java.
uTha9
findViewById\((.+?)\)\s+as\s+([A-Za-z0-9?]+)bekerja lebih baik untuk saya. Ini mencegah beberapa kode baris tidak berakhir @GustavKarlsson
pengguna3680200
1
Tautan tidak mengatakan itu.
Alston
7

Andoid O mengubah api findViewById dari

publik Lihat findViewById (int id);

untuk

publik final T findViewById (int id)

jadi, jika Anda menargetkan API 26, Anda bisa mengubahnya

val listView = findViewById (R.id.list) sebagai ListView

untuk

val listView = findViewById (R.id.list)

atau

val listView: ListView = findViewById (R.id.list)

Trinea
sumber
4

Bekerja

API Level 25 atau di bawahnya gunakan ini

    var et_user_name = findViewById(R.id.et_user_name) as EditText

API Level 26 atau Di Atas gunakan ini

    val et_user_name: EditText = findViewById(R.id.et_user_name)

Selamat Coding!

Keshav Gera
sumber
2

Ubah kode Anda menjadi ini. Tempat terjadinya perubahan utama ditandai dengan tanda bintang.

package com.phenakit.tg.phenakit

import android.content.Context
import android.os.Bundle
import android.support.design.widget.BottomNavigationView
import android.support.v7.app.AppCompatActivity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ListView
import android.widget.TextView

public class MainActivity : AppCompatActivity() {

    private var mTextMessage: TextView? = null

    private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.navigation_home -> {
                mTextMessage!!.setText(R.string.title_home)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_dashboard -> {
                mTextMessage!!.setText(R.string.title_dashboard)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_notifications -> {
                setContentView(R.layout.activity_list_view)
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mTextMessage = findViewById(R.id.message) as TextView?
        val navigation = findViewById(R.id.navigation) as BottomNavigationView
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)


        **val listView = findViewById<ListView>(R.id.list)**



        **listView?.adapter = ListExampleAdapter(this)**
    }

    private class ListExampleAdapter(context: Context) : BaseAdapter() {
        internal var sList = arrayOf("Eins", "Zwei", "Drei")
        private  val mInflator: LayoutInflater

        init {
            this.mInflator = LayoutInflater.from(context)
        }

        override fun getCount(): Int {
            return sList.size
        }

        override fun getItem(position: Int): Any {
            return sList[position]
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
            val view: View?
            val vh: ListRowHolder

            if(convertView == null) {
                view = this.mInflator.inflate(R.layout.list_row, parent, false)
                vh = ListRowHolder(view)
                view.tag = vh
            } else {
                view = convertView
                vh = view.tag as ListRowHolder
            }

            vh.label.text = sList[position]
            return view
        }
    }

    private class ListRowHolder(row: View?) {
        public var label: TextView

        **init { this.label = row?.findViewById<TextView?>(R.id.label) as TextView }**
    }
}
Alf Moh
sumber
Jika Anda menargetkan API 26 di App Anda, maka jawaban di bawah ini adalah jawaban yang benar. val listView = findViewById<ListView>(R.id.list)
EricWas Diambil
@ericWasTaken Ya, Anda benar. Kompilator diharapkan menyimpulkan tipe dari konten di dalam tanda kurung. Terkadang gagal saat itu. Kode Anda juga benar. Akan memperbarui jawaban saya untuk mencerminkan perubahan.
Alf Moh