如何更改此函数以摆脱冗余 SAM 构造函数?
所以,我想制作 SetOnClickListener
来负责打开gallery
。它可以工作,但是当我尝试将代码添加到 commit
到 github
时,我不能这样做,因为我使用了冗余 SAM-Constructor
。所以我的问题是,如何更改我的代码,这样它就可以在没有它的情况下工作?
class MainActivity : AppCompatActivity() {
private var dialogView: View? = null
private val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
it?.let { uri ->
dialogView?.findViewById<ImageView>(R.id.imageChange)?.setImageURI(it)
}?:run {
Log.e("MainActivity", "URI not present")
}
})
private val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
it?.let { uri ->
dialogView?.findViewById<VideoView>(R.id.videoChange)?.setVideoURI(it)
}?: run{
Log.e("MainActivity", "URI not present")
}
})
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
bottomNavigationView.background = null
bottomNavigationView.menu.findItem(R.id.placeholder).isEnabled = false
replaceFragment(HomeFragment())
bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.home -> replaceFragment(HomeFragment())
R.id.player -> replaceFragment(PlayerFragment())
R.id.profile -> replaceFragment(ProfileFragment())
R.id.settings -> replaceFragment(SettingsFragment())
}
true
}
popupAddButton.setOnClickListener {
showDialog()
}
}
private fun replaceFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment)
transaction.commit()
}
@SuppressLint("InflateParams")
private fun showDialog() { //this is for popupWindow
dialogView = layoutInflater.inflate(R.layout.popup, null)
val dialog = Dialog(this)
val titleEditText = dialogView?.findViewById<EditText>(R.id.titleEdit) //popUp edit field title
val descEditText = dialogView?.findViewById<EditText>(R.id.description) //popUp edit field description
dialogView?.addImage?.setOnClickListener {
getPreviewImage.launch("image/*")
}
dialogView?.addVideo?.setOnClickListener {
getPreviewVideo.launch("video/*")
}
dialogView?.addButton?.setOnClickListener {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
if (titleEditText?.text?.isEmpty() == true || descEditText?.text?.isEmpty() == true){
Toast.makeText(applicationContext, "add required data", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(applicationContext, "Added", Toast.LENGTH_SHORT).show()
}
}
dialog.setContentView(dialogView!!)
dialog.show()
}
}
So, i want to make SetOnClickListener
that will be responsible for opening gallery
. It works, but when i try to add code to commit
to github
i can't, because i used Redundant SAM-Constructor
. So my question is, how to change my code, so it will work without it?
class MainActivity : AppCompatActivity() {
private var dialogView: View? = null
private val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
it?.let { uri ->
dialogView?.findViewById<ImageView>(R.id.imageChange)?.setImageURI(it)
}?:run {
Log.e("MainActivity", "URI not present")
}
})
private val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
it?.let { uri ->
dialogView?.findViewById<VideoView>(R.id.videoChange)?.setVideoURI(it)
}?: run{
Log.e("MainActivity", "URI not present")
}
})
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
bottomNavigationView.background = null
bottomNavigationView.menu.findItem(R.id.placeholder).isEnabled = false
replaceFragment(HomeFragment())
bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.home -> replaceFragment(HomeFragment())
R.id.player -> replaceFragment(PlayerFragment())
R.id.profile -> replaceFragment(ProfileFragment())
R.id.settings -> replaceFragment(SettingsFragment())
}
true
}
popupAddButton.setOnClickListener {
showDialog()
}
}
private fun replaceFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment)
transaction.commit()
}
@SuppressLint("InflateParams")
private fun showDialog() { //this is for popupWindow
dialogView = layoutInflater.inflate(R.layout.popup, null)
val dialog = Dialog(this)
val titleEditText = dialogView?.findViewById<EditText>(R.id.titleEdit) //popUp edit field title
val descEditText = dialogView?.findViewById<EditText>(R.id.description) //popUp edit field description
dialogView?.addImage?.setOnClickListener {
getPreviewImage.launch("image/*")
}
dialogView?.addVideo?.setOnClickListener {
getPreviewVideo.launch("video/*")
}
dialogView?.addButton?.setOnClickListener {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
if (titleEditText?.text?.isEmpty() == true || descEditText?.text?.isEmpty() == true){
Toast.makeText(applicationContext, "add required data", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(applicationContext, "Added", Toast.LENGTH_SHORT).show()
}
}
dialog.setContentView(dialogView!!)
dialog.show()
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我猜你的意思是你尝试推送的 Git 存储库的某些 lint 规则不允许冗余 SAM 构造函数。
SAM 构造函数是指您使用 Kotlin 为函数式接口提供的假“构造函数”。对于任何 Java 函数式接口 (SAM)(或 Kotlin
fun
接口),Kotlin 都会创建一个看起来像构造函数的隐式内联函数。它使用该接口的名称作为函数名称,并采用与 SAM 签名匹配的函数引用参数。例如,如果您在 Java 中定义此接口
,或者如果您在 Kotlin 中定义它,则
Kotlin 会隐式创建此函数。你在任何地方都看不到它,但你可以使用它。它只是内联的,因此不能在 Java 中或通过反射访问。
当您想要创建该接口的实例以存储在属性中时,可以使用此假构造函数。当您传递 lambda 作为函数的最后一个参数时,不需要使用此 SAM 构造函数,因为您可以直接传递 lambda,而不调用此构造函数。 Kotlin 自动知道要从 lambda 构建什么接口。*
因此,您的代码
正在使用冗余 SAM 构造函数,并且可以替换为
Youalsoused a Redundant SAM constructor for
val getPreviewVideo
.* 一个例外是当函数重载采用不同的接口作为最后一个参数时。然后,您将需要假构造函数来区分构造函数。
旁注:像这样链接作用域函数是不好的做法 (
?.let
...? :运行
)。除了难以阅读之外,很容易意外地执行某些操作,从而导致两个块都被执行。例如,如果 URI 不为 null,但dialogView
为 null,则您的run
块无论如何都会执行,因为let
的计算结果为 null。我会这样写:I'm guessing that what you mean is that some lint rule for the Git repo you're trying to push to doesn't allow redundant SAM constructors.
A SAM constructor is when you use a fake "constructor" supplied by Kotlin for functional interfaces. For any Java functional interface (SAM) (or Kotlin
fun
interface), Kotlin creates an implicit inline function that looks like a constructor. It uses the name of that interface as the function name and takes a parameter of a functional reference matching the signature of the SAM.So for example, if you define this interface in Java
or if you defined it in Kotlin as
Kotlin implicitly creates this function. You can't see it anywhere but you can use it. It's inline only so cannot be accessed in Java or by reflection.
This fake constructor is for when you want to create an instance of that interface to store in a property. You don't need to use this SAM constructor when you are passing a lambda as the last argument of a function, because you can just pass the lambda directly without calling this constructor. Kotlin automatically knows what interface to build out of the lambda.*
So your code like
is using a redundant SAM constructor and can be replaced with
You also used a redundant SAM constructor for
val getPreviewVideo
.* An exception is when there are overloads of a function that take different interfaces as the last parameter. Then you would need the fake constructor to distinguish between them for the constructor.
Side note: it is bad practice to chain scope functions like that (
?.let
...?:run
). Aside from being hard to read, it is very easy to accidentally do something that will cause both blocks to be executed. For example, if the URI is not null butdialogView
is null, yourrun
block will be executed anyway becauselet
will evaluate to null. I would write it like this: