【问题标题】:Call method from Kotlin classKotlin 类的调用方法
【发布时间】:2017-01-22 05:27:12
【问题描述】:

我有一个 util Kotlin 类,我在其中设置工具栏标题、隐藏或显示工具栏取决于片段:

class MyToolbarUtils() {

    fun hideToolbar(activity: Activity) {
        (activity as MainActivity).supportActionBar!!.hide()
    }

    fun showToolbar(activity: Activity, tag: String) {
        setToolbarTitle(tag, activity)
        (activity as MainActivity).supportActionBar!!.show()
    }

    fun setToolbarTitle(tag: String, activity: Activity) {
        var title = ""
        when (tag) {
            "Main_fragment" -> title = activity.resources.getString(R.string.Main_screen)
            "Add_note" -> title = activity.resources.getString(R.string.Add_note)
        }
        activity.title = title
    }
}

如何从 Fragment 调用 showToolbar(...)? 我刚试过MyToolbarUtils.showToolbar(..),但不可能

我发现只有一种方法是:

val setToolbarTitle = MyToolbarUtils()
setToolbarTitle.showToolbar(activity, tag)

但必须有更好的方法来做到这一点..

【问题讨论】:

  • Kotlin 有静态方法吗?如果不是,那么您所展示的内容是有道理的
  • 如果所有这些都只适用于一个类,MainActivity 为什么它们就不是那个类的方法?
  • 您询问了xy question ...您决定了一个编程问题的答案,然后使用该预先决定的答案寻求帮助。但在这种情况下,您的答案根本不是正确的。在这种情况下,惯用的 Kotlin 不会使用静态或对象声明,而是使用 stackoverflow.com/a/39499145/3679676

标签: android fragment toolbar kotlin


【解决方案1】:

将您的 class 转换为 object,它的工作原理应该类似于 java 静态方法。

您可以在此处获取更多信息:https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations

【讨论】:

  • 那么如何从片段和适配器调用该函数??
  • @chandanicpatel...Class.Method() 或使用上面的示例...MyToolbarUtils.showToolbar()。 OP把这个放在他的问题中
【解决方案2】:

听起来像MyToolbarUtils 应该是object declaration 而不是类。

另一种方法是在文件的顶层(而不是在任何类中)声明此类内部的函数,并通过它们的简单名称来引用它们。

【讨论】:

    【解决方案3】:

    其他人回答了如何让你的函数感觉像静态方法,但对于这个用例,你有一个更惯用的选择。

    Kotlin 中的扩展函数替换 Java 中的静态实用程序类:

    既然你的所有函数都将Activity作为参数,为什么不使用extension functions并让它们扩展ActivityMainActivity类呢?

    fun MainActivity.hideToolbar() {
        supportActionBar!!.hide()
    }
    
    fun MainActivity.showToolbar(tag: String) {
        setToolbarTitle(tag)
        supportActionBar!!.show()
    }
    
    fun Activity.setToolbarTitle(tag: String) {
        title = when (tag) {
            "Main_fragment" -> title = resources.getString(R.string.Main_screen)
            "Add_note" -> title = resources.getString(R.string.Add_note)
            else -> "" // or did you mean this to be an exception?
        }
    }
    

    现在它们都在您的 MainActivityActivity 类的上下文中(this 现在是其中之一的实例),您不必在其他不相关的 @987654332 中寻找它们@ 班级。每当您在活动类中时,您都可以简单地:

    showToolbar("Main_fragment")
    

    或从您引用某个活动的其他地方:

    // you have a reference of MainActivity type
    myMainActivity.showToolbar("Main_fragment")
    
    // you have a reference you can cast to MainActivity type
    (someActivity as MainActivity).showToolbar("Main_fragment")
    
    // this function works with any Activity
    someActivity.setToolbarTitle("Add_note")
    

    还要注意,我清理了一点代码,用when as an expression设置标题,还去掉了var(需要var的时候很少见,所以总要想想怎么工作与val)。作为表达式,when 将需要一个 else 子句,所以我将其设置为与您默认的 "" 空字符串相同。

    类方法的替代方案:

    由于所有 3 种方法都需要 MainActivity 的实例(基于它们的转换),为什么不将它们作为成员函数放入 MainActivity

    class MainActivity ... {
        ...
    
        fun hideToolbar() {
            supportActionBar!!.hide()
        }
    
        fun showToolbar(tag: String) {
            setToolbarTitle(tag)
            supportActionBar!!.show()
        }
    
        fun setToolbarTitle(tag: String) {
            title = when (tag) {
                "Main_fragment" -> title = resources.getString(R.string.Main_screen)
                "Add_note" -> title = resources.getString(R.string.Add_note)
                else -> "" // or did you mean this to be an exception?
            }
        }
    }
    

    并从对MainActivity 的任何引用中调用它们。

    作为对象声明的替代方案:

    最后,正如其他人所建议的那样,为了完整起见,这里它们位于一个实用程序类中,其作用类似于静态变量,而是单例 object declaration 上的方法:

    object MyToolbarUtils() {
        fun hideToolbar(activity: MainActivity) {
            activity.supportActionBar!!.hide()
        }
    
        fun showToolbar(activity: MainActivity, tag: String) {
            setToolbarTitle(activity, tag)
            activity.supportActionBar!!.show()
        }
    
        fun setToolbarTitle(activity: Activity, tag: String) {
            activity.title = when (tag) {
                "Main_fragment" -> title = resources.getString(R.string.Main_screen)
                "Add_note" -> title = resources.getString(R.string.Add_note)
                else -> "" // or did you mean this to be an exception?
            }
        }
    }
    

    但我认为这是扩展另一个类的功能的最糟糕和最不像 Kotlin 的方式。像 SomethingUtils 这样充满静态的类/对象意味着您可能应该改写 extension functions

    【讨论】:

      【解决方案4】:

      使用 object 关键字在 Kotlin 中创建一个单例类,并在 Java 中调用 Kotlin 单例类,如下所示:

      object SampleSingleton {
         fun someMethod() { 
           println("I love coding")
         }
      }
      

      如果来自Java则如下

      public static void main(String args[]) {
         SampleSingleton.INSTANCE.someMethod();
      }
      

      或来自 Kotlin 类如下

      SampleSingleton.someMethod()
      

      【讨论】:

        【解决方案5】:

        我不确定这是否符合您对更好方法的定义,但更简单的方法是替换您的两行代码:

        val setToolbarTitle = MyToolbarUtils()
        setToolbarTitle.showToolbar(activity, tag)
        

        只有这一行;

        MyToolbarUtils().showToolbar(activity, tag)
        

        编码愉快!

        【讨论】:

          【解决方案6】:
          // Kotlin
          
          @file:JvmName("DemoUtils")
          package demo
          
          class ClassInKotlin
          
          fun methodInKotlin() {
          }
          
          // Java
          new demo.ClassInKotlin();
          demo.DemoUtils.methodInKotlin();
          

          试试这个。这应该可以。

          【讨论】:

          • 这真的没有意义。他不是试图从 Java 调用代码,你也不需要@JvmName 没有ClassInKotlin 也不需要来自 Java 的调用。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多