【问题标题】:Not able to "findViewById" in Kotlin. Getting error "Type inference failed"在 Kotlin 中无法“findViewById”。收到错误“类型推断失败”
【发布时间】:2017-12-10 13:10:53
【问题描述】:

当我尝试通过 id 查找 RecycleView 时出现以下错误。

错误:- 类型推断失败:没有足够的信息来推断参数 T

代码:

class FirstRecycleViewExample : AppCompatActivity() {
    val data = arrayListOf<String>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.first_recycleview)

        val recycler_view =  findViewById(R.id.recycler_view) as RecyclerView ///IN THIS LINE I AM GETTING THE ERROR

        data.add("First Data")
        data.add("Second Data")
        data.add("Third Data")
        data.add("Forth Data")
        data.add("Fifth Data")

        //creating our adapter
        val adapter = CustomRecycleAdapter(data)

        //now adding the adapter to recyclerview
        recycler_view.adapter = adapter
    }
}

【问题讨论】:

    标签: android android-layout kotlin type-inference


    【解决方案1】:

    尝试类似:

    val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
    

    您也可以使用Kotlin Android Extensions。检查文档here
    有了它,你可以直接在你的代码中调用recycler_view

    Kotlin Android 扩展:

    • 在您的应用程序中gradle.build 添加apply plugin: 'kotlin-android-extensions'
    • 在您的课程中添加 import kotlinx.android.synthetic.main.&lt;layout&gt;.* 的导入,其中 &lt;layout&gt; 是您的布局文件名。
    • 就是这样,您可以直接在代码中调用recycler_view

    它是如何工作的?第一次调用recycler_view 时,对findViewById 的调用完成并缓存

    【讨论】:

    • 在最新版本中,我收到警告要从 中删除类型。由于Android工作室强迫我在使用它时只使用钻石运算符&lt;&gt;,所以它给出了错误。
    【解决方案2】:

    您处于 API 级别 26,其中 findViewById 的返回类型现在是通用的 T 而不是 View,因此可以推断。可以查看相关的更新日志here

    所以你应该能够做到这一点:

    val recycler_view = findViewById<RecyclerView>(R.id.recycler_view)
    

    或者这个:

    val recycler_view: RecyclerView = findViewById(R.id.recycler_view)
    

    【讨论】:

      【解决方案3】:

      已弃用

      Kotlin 中,我们可以在不使用findViewById 语法的情况下获取视图的id。

      例如,我们使用下面的布局,我们将获取视图的 id 并执行操作

      布局

      <?xml version="1.0" encoding="utf-8"?>
      <FrameLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
      
          <TextView
              android:id="@+id/welcomeMessage"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:text="Hello World!"/>
      
      </FrameLayout>
      

      我们可以通过以下代码找到视图的id

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)
       
          welcomeMessage.text = "Hello Kotlin!" ////WE ARE GETTING THE IDS WITHOUT USING THE FINDVIEWBYID syntax
      }
      

      怎么做?

      为了能够使用它,您需要一个特殊的导入(我在下面写的那个),但 IDE 能够自动导入它。再简单不过了!

      import kotlinx.android.synthetic.main.YOUR_LAYOUT_NAME.*/// HERE "YOUR_LAYOUT_NAME" IS YOUR LAYOUT NAME WHICH U HAVE INFLATED IN onCreate()/onCreateView() 
      

      我们需要在不使用findviewbyid语法的情况下导入这个属性来获取视图的id。

      有关此主题的更多信息,请参阅此链接:- Click here

      更新

      现在不推荐使用 kotlin-android-extensions ,而不是使用 kotlin 提供的绑定,我们现在可以使用 View-Binding 并且它的工作原理与上述解决方案相同,只是您需要使用在你的应用程序gradle下面

      android {
          ...
          buildFeatures {
              viewBinding true
          }
      }
      

      【讨论】:

      • 绝妙的解决方案!帮了我很多!
      • 使用这个解决方案有什么缺点吗?该解决方案看起来很棒,并且可以使代码更简洁。
      • @Ikdhruw 你也可以使用视图绑定,因为我已经更新了上面的解决方案
      【解决方案4】:

      通常 Kotlin 可以使用括号中提供的信息推断您的类型。

      在这种情况下,它不能,所以你必须像这样明确指定它

      findViewById<RecyclerView>(R.id.recycler_view)
      

      虽然不太确定类型,但你应该这样指定它

      我想补充一点,使用Anko,您可以进一步简化您的代码,如下所示:

      val recycler_view : RecyclerView =  find(R.id.recycler_view)
      

      【讨论】:

        【解决方案5】:

        为您的代码添加这一行作为您使用的控制器。

        val tvHello = findViewById<TextView>(R.id.tvHello)
        

        【讨论】:

          【解决方案6】:

          您可以忽略在 kotlin 中为变量提供 id。你只需要使用一个插件

          将其粘贴到您的 gradle 中

           apply plugin: 'kotlin-android-extensions'
          

          然后你不需要为var分配id,你可以这样做

           recycler_view.setAdapter(youradapter);
          

          【讨论】:

          • 请提供拒绝投票的理由。
          【解决方案7】:

          无法访问像 OP 一样的 ui 组件,在 app gradle 中需要如下所示:

          plugins {
              ...
              id 'kotlin-android-extensions'
          }
          

          即使在添加此行之后,android studio 仍然无法自动解析 kotlin 合成的导入,因此您可能需要使缓存无效并重新启动。

          如果仍然无法正常工作,请根据视图手动导入

          • 活动/片段视图:导入 kotlinx.android.synthetic.main..*
          • 普通视图: 导入 kotlinx.android.synthetic.main..view.*

          更新 - 2

          如果您收到此信息警告 -

          警告:“kotlin-android-extensions”Gradle 插件已弃用。

          插件“kotlin-android-extensions”将被弃用。 因此,在您的应用程序 gradle 中添加以下内容

          android {
              ...
              buildFeatures {
                  viewBinding true
              }
          }
          

          【讨论】:

            【解决方案8】:

            试试这个:

            这里bind 通用函数用于绑定视图。它的一般功能可以用于任何视图。

            class MyActivity : AppCompatActivity() {
                private lateinit var recycler_view : RecyclerView
                override fun onCreate(savedInstanceState: Bundle?) {
                    ...
                    recycler_view = bind(R.id.recycler_view)
                }
            }
            
            fun <T : View> Activity.bind(@IdRes res : Int) : T {
                @Suppress("UNCHECKED_CAST")    
                return findViewById(res) as T
            }
            

            【讨论】:

            • 请为您的代码添加解释。不鼓励仅使用代码回答。
            • 已添加。 @WilliMentzel
            【解决方案9】:

            您甚至不必创建一个对象来使用视图执行操作。 你可以只使用id。例如, 科特林

            recycle_view.adapter = adapter
            

            等同于, Java

            RecycleView recycle_view = (RecycleView) findViewById(recycle_view);
            recycle_view.setAdapter(adapter);
            

            【讨论】:

              猜你喜欢
              • 2018-08-21
              • 2020-12-30
              • 2019-09-05
              • 2018-05-15
              • 1970-01-01
              • 1970-01-01
              • 2018-05-03
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多