为什么设置 onClickListener 只工作一次?
Why is setting onClickListener working once?
我想将我使用的非常可靠的项目结构迁移到 Kotlin。我首先尝试了基础知识:活动和片段交易。看起来很简单:
class MainActivity : AppCompatActivity(), SomeInterface {
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
val mainFragment = supportFragmentManager.findFragmentById(R.id.fragment_main) as MainActionsFragment?
?: MainActionsFragment.newInstance()
supportFragmentManager.inTransaction {
add(R.id.container_main, mainFragment)
}
}
private val anotherFragment by lazy {
supportFragmentManager.findFragmentById(R.id.another_fragment) as AnotherFragment?
?: AnotherFragment.newInstance()
}
override fun myInterfaceMethod() {
replaceFragment(anotherFragment, R.id.container_main)
}
}
class MainActionsFragment : Fragment() {
val btnSale: Button by bindView(R.id.btn_sale)
val btnVisit: Button by bindView(R.id.btn_visit)
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater!!.inflate(R.layout.fragment_main, container, false)
}
override fun onResume() {
super.onResume()
btnSale.setOnClickListener{ _ ->
listener.requestAction(SaleType.SALE)
}
btnVisit.setOnClickListener{ _ ->
listener.requestAction(SaleType.VISIT)
}
}
}
Extensions.kt
fun AppCompatActivity.replaceFragment(fragment: Fragment, @IdRes frameId: Int) {
supportFragmentManager.inTransaction {
replace(frameId, fragment)
.addToBackStack(fragment.tag)
}
}
inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) {
beginTransaction()
.func()
.commit()
}
现在,MainActionsFragment
拥有两个按钮。一切都按预期工作,第一次点击其中任何一个都会带我到所需的片段。但是,一旦我按下后退按钮并再次看到我的两个按钮,它们的点击侦听器就消失了。这几乎是翻译成 Kotlin 的标准做事方式,除了它很酷的新功能外没有什么特别的。我尝试将 onClickListeners 设置为 onCreateView()
但它崩溃了:
Caused by: kotlin.KotlinNullPointerException
at kotterknife.ButterKnifeKt$viewFinder.invoke(ButterKnife.kt:95)
at kotterknife.ButterKnifeKt$viewFinder.invoke(ButterKnife.kt)
at kotterknife.ButterKnifeKt$required.invoke(ButterKnife.kt:104)
at kotterknife.ButterKnifeKt$required.invoke(ButterKnife.kt)
at kotterknife.Lazy.getValue(ButterKnife.kt:125)
所以,尽管 Kotlin 非常酷,但我在做基础知识时遇到了困难,而且我对迁移感到沮丧。我真的做错了吗?或者为什么设置一个简单的点击监听器如此令人沮丧?
谢谢。
您必须将 ButterKnife 绑定的变量设置为 lateinit var
而不是 val
。尝试
@BindView(R.id.btn_sale)
lateinit var title: Button
@BindView(R.id.btn_visit)
lateinit var title: Button
解决方案:通过删除 KotterKnife
和 ButterKnife
并使用 android 的 findViewById
解决了这个问题。我想语言的优点之一和框架的进步使一些库过时或不必要。
我想将我使用的非常可靠的项目结构迁移到 Kotlin。我首先尝试了基础知识:活动和片段交易。看起来很简单:
class MainActivity : AppCompatActivity(), SomeInterface {
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
val mainFragment = supportFragmentManager.findFragmentById(R.id.fragment_main) as MainActionsFragment?
?: MainActionsFragment.newInstance()
supportFragmentManager.inTransaction {
add(R.id.container_main, mainFragment)
}
}
private val anotherFragment by lazy {
supportFragmentManager.findFragmentById(R.id.another_fragment) as AnotherFragment?
?: AnotherFragment.newInstance()
}
override fun myInterfaceMethod() {
replaceFragment(anotherFragment, R.id.container_main)
}
}
class MainActionsFragment : Fragment() {
val btnSale: Button by bindView(R.id.btn_sale)
val btnVisit: Button by bindView(R.id.btn_visit)
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater!!.inflate(R.layout.fragment_main, container, false)
}
override fun onResume() {
super.onResume()
btnSale.setOnClickListener{ _ ->
listener.requestAction(SaleType.SALE)
}
btnVisit.setOnClickListener{ _ ->
listener.requestAction(SaleType.VISIT)
}
}
}
Extensions.kt
fun AppCompatActivity.replaceFragment(fragment: Fragment, @IdRes frameId: Int) {
supportFragmentManager.inTransaction {
replace(frameId, fragment)
.addToBackStack(fragment.tag)
}
}
inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) {
beginTransaction()
.func()
.commit()
}
现在,MainActionsFragment
拥有两个按钮。一切都按预期工作,第一次点击其中任何一个都会带我到所需的片段。但是,一旦我按下后退按钮并再次看到我的两个按钮,它们的点击侦听器就消失了。这几乎是翻译成 Kotlin 的标准做事方式,除了它很酷的新功能外没有什么特别的。我尝试将 onClickListeners 设置为 onCreateView()
但它崩溃了:
Caused by: kotlin.KotlinNullPointerException at kotterknife.ButterKnifeKt$viewFinder.invoke(ButterKnife.kt:95) at kotterknife.ButterKnifeKt$viewFinder.invoke(ButterKnife.kt) at kotterknife.ButterKnifeKt$required.invoke(ButterKnife.kt:104) at kotterknife.ButterKnifeKt$required.invoke(ButterKnife.kt) at kotterknife.Lazy.getValue(ButterKnife.kt:125)
所以,尽管 Kotlin 非常酷,但我在做基础知识时遇到了困难,而且我对迁移感到沮丧。我真的做错了吗?或者为什么设置一个简单的点击监听器如此令人沮丧?
谢谢。
您必须将 ButterKnife 绑定的变量设置为 lateinit var
而不是 val
。尝试
@BindView(R.id.btn_sale)
lateinit var title: Button
@BindView(R.id.btn_visit)
lateinit var title: Button
解决方案:通过删除 KotterKnife
和 ButterKnife
并使用 android 的 findViewById
解决了这个问题。我想语言的优点之一和框架的进步使一些库过时或不必要。