Kotlin ve Android ile "T parametresini çıkarmak için yeterli bilgi yok"


111

Aşağıdaki ListView'i Kotlin kullanarak Android uygulamamda kopyalamaya çalışıyorum: https://github.com/bidrohi/KotlinListView .

Maalesef kendim çözemediğim bir hata alıyorum. İşte kodum:

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
    }
}
}

Düzenler tam olarak buradaki gibidir: https://github.com/bidrohi/KotlinListView/tree/master/app/src/main/res/layout

Aldığım tam hata mesajı şudur: Hata: (92, 31) Tür çıkarımı başarısız oldu: Eğlenceli findViewById'de T parametresini çıkarmak için yeterli bilgi yok (p0: Int): T! Lütfen açıkça belirtin.

Alabileceğim her yardım için minnettar olurum.


2
Eğer değiştirmeyi deneyin Can this.label = ... as TextViewiçin this.label = row?.findViewById<TextView>ve bu kadar benzer do val listView = ...? Lütfen bunun işe yarayıp yaramadığını bana bildirin, böylece bu durumda bunu uygun bir cevap haline getirebilirim.
Christian Brüggemann

1
Hangi satır hataya neden olur?
voddan

Problemi daha küçük bir örnekle gösterebilir misiniz?
voddan

@ ChristianBrüggemann Bunu beğenin : i.imgur.com/ZeWKjt5.png ve bu: i.imgur.com/Can7w0p.png ? Düzenlemelerinizle şimdi bu hatalar var: i.imgur.com/qqPAjrL.png
Timo Güntner

1
Bunu deneyin this.label = row? .FindViewById <TextView> (R.id.label) TextView olarak
Alf Moh

Yanıtlar:


225

API seviyesi 26 (veya üzeri) kullanıyor olmalısınız. Bu sürümün imzasını değiştirdi View.findViewById()- buraya bakın https://developer.android.com/about/versions/oreo/android-8.0-changes#fvbi-signature

Dolayısıyla sonucun findViewByIdbelirsiz olduğu durumlarda, türü sağlamanız gerekir:

1 / Değiştir

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

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

2 / Değiştir

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

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

Unutmayın ki 2 / atama işlemi yalnızca rownull yapılabilir olduğu için gereklidir . Eğer label null yapılabilir olsaydı veya rownull yapılamaz hale getirdiyseniz, gerekli olmazdı.


10
Bunu toplu olarak çözmek için: Yolda Değiştir iletişim kutusunu (Ctrl + Shift + R) açın ve normal ifade kutusunu işaretleyin. Değiştir findViewById\((.+?)\)\s+as\s+(.+)ile findViewById<$2>\($1\)ve tüm dosya üzerinde yerini çalıştırın. Neredeyse tüm hatalarımı çözdü.
Gustav Karlsson

1
Varsayılan olarak Görünüm tipini çıkarmak Java'da neden yeterli ve Kotlin'de yeterli değil? findViewById(R.id.tabLayout).setOnClickListener(v-> Log.d(TAG, "login: "));Java için sorun yok.
uTha9

findViewById\((.+?)\)\s+as\s+([A-Za-z0-9?]+)benim için daha iyi çalışıyor. @GustavKarlsson'da bir satır kodunun bitmemesini engeller
user3680200

1
Bağlantı bunu söylemiyor.
Alston

7

Andoid O findViewById api'yi değiştir

genel Görünüm findViewById (int id);

-e

genel nihai T findViewById (int id)

bu nedenle, API 26'yı hedefliyorsanız,

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

-e

val listView = findViewById (R.id.list)

veya

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


4

İşe yarıyor

API Seviye 25 veya altı bunu kullanın

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

API Seviye 26 veya Üstü bunu kullanın

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

Mutlu Kodlama!


2

Kodunuzu buna değiştirin. Ana değişikliklerin gerçekleştiği yer yıldız işaretleriyle işaretlenmiştir.

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 }**
    }
}

Uygulamanızda API 26'yı hedefliyorsanız, aşağıdaki cevap doğru cevaptır. val listView = findViewById<ListView>(R.id.list)
EricWasTaken

@ericWasTaken Evet, haklısınız. Derleyicinin türü parantez içindeki içeriklerden çıkarması beklenir. Bazen bunda başarısız olur. Kodunuz da doğru. Cevabımı değişiklikleri yansıtacak şekilde güncelleyeceğim.
Alf Moh

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.