【问题标题】:"Not enough information to infer parameter T" with Kotlin and Android“没有足够的信息来推断参数 T”与 Kotlin 和 Android
【发布时间】:2017-12-29 05:45:17
【问题描述】:

我正在尝试使用 Kotlin 在我的 Android 应用中复制以下 ListView:https://github.com/bidrohi/KotlinListView

很遗憾,我遇到了一个我自己无法解决的错误。 这是我的代码:

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

布局与此处完全相同:https://github.com/bidrohi/KotlinListView/tree/master/app/src/main/res/layout

我收到的完整错误消息是: 错误:(92, 31) 类型推断失败:没有足够的信息来推断 fun findViewById(p0: Int) 中的参数 T:T! 请明确指定。

如果能得到任何帮助,我将不胜感激。

【问题讨论】:

  • 您可以尝试将this.label = ... as TextView 更改为this.label = row?.findViewById<TextView> 并为val listView = ... 进行类似的操作吗?请让我知道这是否可行,以便我可以在这种情况下做出正确的回答。
  • 哪一行导致错误?
  • 你能用一个更小的例子来证明这个问题吗?
  • @ChristianBrüggemann 喜欢这个:i.imgur.com/ZeWKjt5.png 和这个:i.imgur.com/Can7w0p.png ?通过您的编辑,现在出现以下错误:i.imgur.com/qqPAjrL.png
  • 试试 this.label = row?.findViewById(R.id.label) as TextView

标签: android kotlin android-8.0-oreo


【解决方案1】:

您必须使用 API 级别 26(或更高)。此版本更改了View.findViewById() 的签名 - 请参阅此处https://developer.android.com/about/versions/oreo/android-8.0-changes#fvbi-signature

因此,在您的情况下,findViewById 的结果不明确,您需要提供类型:

1/ 改变

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

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

2/改变

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

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

请注意,在 2/ 中仅需要强制转换,因为 row 可以为空。如果label 也可以为空,或者如果您将row 设为不可为空,则不需要。

【讨论】:

  • 以下是批量解决此问题的方法:打开 在路径中替换 对话框 (Ctrl+Shift+R) 并选中正则表达式框。将 findViewById\((.+?)\)\s+as\s+(.+) 替换为 findViewById<$2>\($1\) 并对所有文件运行替换。它解决了我几乎所有的错误。
  • 为什么在 Java 中默认推断 View 类型就足够了,而在 Kotlin 中则不够? findViewById(R.id.tabLayout).setOnClickListener(v-> Log.d(TAG, "login: ")); 这对 Java 来说没问题。
  • findViewById\((.+?)\)\s+as\s+([A-Za-z0-9?]+) 对我来说效果更好。它可以防止某些一行代码没有结束@GustavKarlsson
  • 链接没有这么说。
【解决方案2】:

Andoid O 更改 findViewById api 来自

公共视图 findViewById(int id);

public final T findViewById(int id)

所以,如果你的目标是 API 26,你可以改变

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

val listView = findViewById(R.id.list)

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

【讨论】:

    【解决方案3】:

    它的工作原理

    API Level 25 或以下使用这个

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

    API Level 26 或以上使用这个

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

    编码愉快!

    【讨论】:

      【解决方案4】:

      将您的代码更改为此。发生主要变化的地方用星号标记。

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

      【讨论】:

      • 如果您在您的应用程序中以 API 26 为目标,那么下面的答案就是正确答案。 val listView = findViewById&lt;ListView&gt;(R.id.list)
      • @ericWasTaken 是的,你是对的。编译器应该从括号中的内容推断类型。有时它会失败。你的代码也是正确的。将更新我的答案以反映更改。
      【解决方案5】:

      我建议你使用synthetics kotlin Android 扩展:

      https://kotlinlang.org/docs/tutorials/android-plugin.html

      https://antonioleiva.com/kotlin-android-extensions/

      在您的情况下,代码将是这样的:

      init {
         this.label = row.label
      }
      

      就这么简单;)

      【讨论】:

        【解决方案6】:

        在 android 12 中,从您的代码中删除 as 并将您的 model 放在 getParcelableExtra 前面。

        改变

        intent.getParcelableExtra("MyModel") as MyModel
        

        intent.getParcelableExtra `<MyModel>` ("MyModel")!!
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-02-11
          • 1970-01-01
          • 2020-03-11
          • 1970-01-01
          • 2020-03-31
          • 1970-01-01
          • 1970-01-01
          • 2020-03-19
          相关资源
          最近更新 更多