2017-05-25 100 views
3

我正在嘗試從一個操作傳遞一個偵聽器到一個類(一個適配器)。傳遞偵聽器對象作爲函數參數在kotlin

在java中(代碼從Action):

private void setListeners() { 
    adapterRecyclerView.setListener(
      new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        SomeCodehere.... 
       } 
      }); 
} 

(代碼從適配器)

public void setListener(View.OnClickListener listener) { 
    this.listener = listener; 
} 

它的工作原理。

現在我試圖traitslate kotlin。我首先翻譯動作(將動作翻譯爲kotlin):

private fun setListeners() { 
    // !! is not fine i know 
    adapterRecyclerView!!.setListener { v -> 
          SomeCodehere.... 
    } 
} 

此時仍然有效。使用適配器的代碼仍然在java和kotlin中類的代碼。現在我將適配器翻譯成kotlin:

fun setListener(listener: View.OnClickListener) { 
    this.listener = listener 
} 

現在它不工作。該行動不編譯。

錯誤: 無法推斷此參數「v」的類型。 需要View.OnClickListener。發現(???)單位爲 。

我該如何做演員? 爲什麼要將參數從kotlin傳遞給java工作,並從kotlin傳遞給kotlin,它不會呢?

回答

4

變化

adapterRecyclerView!!.setListener { v -> 
         SomeCodehere.... 
} 

adapterRecyclerView!!.setListener(object : View.OnClickListener { 

}) 

貫徹View.OnClickListener

+0

它的工作,非常感謝你! –

+1

只是一個友好的建議:!!應避免操作員。否則,您將無法利用kotlin的無效安全功能。通過事先檢查adapterRecyclerView的可空性,可以對非空對象進行非精確轉換。 – Ahmad

+0

同意。我只保留了問題中提出的代碼結構 – Joakim

4

的方法在調用Java代碼的您是從SAM轉換爲書面單一方法接口受益的情況下在Java中。然後,當您將接口移植到Kotlin時,它仍然不允許這樣做(Kotlin目前假設您將使用函數引用和lambdas而不是單個方法接口)。

的問題是一樣的,從這個其他類似的問題:Android - Kotlin - object must be declared abstract or implement abstract member

Since this is a Kotin interface, you cannot use the SAM conversion to a Lambda so that is why the other answer previously provided does not work. If this was a Java interface, you could do that. You can track SAM conversions for Kotlin interfaces in KT-7770 .

If you wanted this code to be more idiomatic Kotlin you would want function references or lambdas instead of interfaces, and you should just do that instead of relying on SAM conversion. You can read more about that in Higher-Order Functions and Lambdas . This is outside the scope of your question to go into more detail.

因此在通過@joakim另一個答覆中提到,你必須通過實現此接口的類的實例。這就是所謂的Object Expression,看起來像:

object : View.OnClickListener { 
    override fun onClick(v: View) {...} 
}) 

還是現實,你應該改變的代碼你科特林端口,能夠接受對函數的引用,這樣一個lambda可以直接通過。這會更加地道,你可以像你最初嘗試的那樣稱呼它。