android t类型参数,使用Kotlin和Android,“信息不足以推断参数T”

我正在尝试使用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)类型推断失败:没有足够的信息来有趣地推断参数T findViewById(p0:Int):T!

请明确指定。

我将不胜感激。

您可以尝试将this.label = ... as TextView更改为this.label = row?.findViewById并类似地将其用于val listView = ...吗?请让我知道这是否可行,以便在这种情况下可以做出正确的回答。

哪条线会导致错误?

您能用一个较小的例子来说明问题吗?

@ChristianBrggemann像这样:i.imgur.com/ZeWKjt5.png和这个:i.imgur.com/Can7w0p.png?通过您的编辑,现在出现以下错误:i.imgur.com/qqPAjrL.png

@voddan此行导致错误:this.label = row?.findViewById(R.id.label)as TextView

试试这个this.label = row?.findViewById (R.id.label)作为TextView

@AlfMoh该应用程序现在启动,但之后立即崩溃。现在,调试控制台中的错误为:kotlin.TypeCastException:无法将null强制转换为非null类型的android.widget.ListView

在TextView的末尾添加一个问号

@AlfMoh在末尾带有问号(this.label = row?.findViewById (R.id.label)作为TextView?),我得到以下错误:错误:(94,26)类型不匹配:推断类型是TextView吗?但是应该使用TextView

那这个呢?公共val标签:TextView?初始化{this.label = row?.findViewById (R.id.label)作为TextView吗? }

不幸的是,相同的错误:错误:(94,26)类型不匹配:推断的类型是TextView?但应使用TextView。 Android监视器中的以下内容:java.lang.RuntimeException:无法启动活动ComponentInfo {com.phenakit.tg.phenakit / com.phenakit.tg.phenakit.MainActivity}:kotlin.TypeCastException:无法将null强制转换为非null键入android.widget.ListView @AlfMoh

让我们继续聊天中的讨论。

您必须使用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(R.id.list)

2 /变更

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

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

请注意,在2 /中,仅强制转换,因为row是可为空的。如果label

也可以为空,或者如果您将row设为不可为空,则不需要。

期待我们的地狱多么美好

以下是批量解决此问题的方法:打开"在路径中替换"对话框(Ctrl + Shift + R)并选中"正则表达式"框。 将findViewById\((.+?)\)\s+as\s+(.+)替换为findViewById\($1\),然后对所有文件运行替换。 它解决了我几乎所有的错误。

为什么在Java中默认情况下足以推断View类型而在Kotlin中却不足? findViewById(R.id.tabLayout).setOnClickListener(v-> Log.d(TAG,"login:"));这对于Java是可以的。

findViewById\((.+?)\)\s+as\s+([A-Za-z0-9?]+)对我来说效果更好。 它可以防止某一行代码未结束@GustavKarlsson

链接没有这么说。

Andoid O从以下位置更改find??ViewById api

public View 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)

它的工作

API级别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)

编码愉快!

将代码更改为此。主要更改发生的位置标有星号。

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(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(R.id.label) as TextView }**

}

}

如果您要在应用中定位API 26,则以下答案是正确的答案。 val listView = findViewById(R.id.list)

@ericWasTaken是的,您是对的。 编译器应该从方括号中的内容推断类型。 有时它失败了。 您的代码也是正确的。 将更新我的答案以反映更改。

我建议您使用synthetics kotlin Android扩展名:

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

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

在您的情况下,代码将如下所示:

init {

this.label = row.label

}

就如此容易 ;)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值