Java到Kotlin转换后出现问题,Android Studio中出现错误,无法推断此参数的类型

时间:2018-10-12 22:24:14

标签: java android android-studio kotlin fetch2

当我在Java中转换此方法时:

private void enqueueDownloads() {
    final List<Request> requests = Data.getFetchRequestWithGroupId(GROUP_ID);
    fetch.enqueue(requests, updatedRequests -> {

    }, error -> Timber.d("DownloadListActivity Error: %1$s", error.toString()));

}

导致这种方法存在很多错误:

private fun enqueueDownloads() {
    val requests = Data.getFetchRequestWithGroupId(GROUP_ID)
    fetch.enqueue(requests, { updatedRequests ->

    }, { error -> Timber.d("DownloadListActivity Error: %1\$s", error.toString()) })

}

Kotlin中的此方法在方法fetch.enqueue处有很多错误,其中值updatedRequestserror表示Cannot infer a type for this parameter

所以我将鼠标悬停在方法上,然后单击Ctrl+B,库中的方法声明为:

fun enqueue(requests: List<Request>, func: Func<List<Request>>? = null, func2: Func<Error>? = null): Fetch

/** Pause a queued or downloading download.
 * @param ids ids of downloads to be paused.
 * @param func Callback the paused downloads will be returned on. Note. Only downloads that
 * were paused will be returned in the result list.
 * @param func2 Callback that is called when attempting to pause downloads fail. An error is returned.
 * @throws FetchException if this instance of Fetch has been closed.
 * @return Instance
 * */

该问题与基于方法文档的CallBack有关,但我无法使其正常工作!我怎样才能使它完全成为Kotlin并在Kotlin中进行调用?。

该库为Fetch2,用Kotlin编写。我也看不到库中方法的完整代码。

1 个答案:

答案 0 :(得分:0)

TLDR:您具体情况下的shorting语法为:

fetch.enqueue(requests, Func { updatedRequests ->

}, Func { error -> Timber.d("DownloadListActivity Error: %1\$s", error) })

这里的问题是您正在调用用Kotlin编写的函数。您不能在这里使用短的lambda语法,因为在这种情况下Kotlin不会自动将lambda转换为正确的界面。

  

“ Kotlin具有适当的功能类型,不需要将功能自动转换为Kotlin接口的实现,因此不受支持。” ( source

通常,要在Kotlin中匿名实现(Kotlin)接口,您必须使用成熟的对象语法:

interface KFunc<T> { fun call(result: T) }

val func = object : KFunc<String> {
    override fun call(result: String) {
        println(result)
    }
}

但是Func是用Java定义的接口,因此Kotlin提供了自动转换实用程序,您可以编写

val func: Func<String> = Func {
    result -> println(result)
}

这是因为每个Java接口都有一个自动生成的方法。在这种情况下,将生成以下代码

fun <T> Func(function: (result: T) -> Unit): Func<T> {
    return object : Func<T> {
        override fun call(result: T) {
            function(result) // call the function
        }
    }
}

如果采用Func的方法也是用Java编写的,那么您甚至可以省去Func {}部分。例如。给

public class JavaClass {
    public static void doWithFunc(Func<String> func) {
         func.call("Hello");
    }
}

你可以写

JavaClass.doWithFunc { result -> println(result) }

但是给予

object KotlinClass {
    @JvmStatic
    fun doWithFunc(func: Func<String>) {
        func.call("Hello")
    }
}

您至少必须写

KotlinClass.doWithFunc(Func { result -> println(result) })

另一方面,在Java(8+)中, 在两种情况下都可以使用lambdas

JavaClass.doWithFunc(string -> System.out.println(string));
KotlinClass.doWithFunc(string -> System.out.println(string));

有点混乱。目前,用Kotlin编写的,供Kotlin消费的API不应使用功能接口,而应使用实际的函数参数,即enqueue函数

fun enqueue(requests: List<Request>, func: Func<List<Request>>? = null, func2: Func<Error>? = null): Fetch

理想情况下,他们也会提供

fun enqueue(requests: List<Request>, func: ((List<Request>) -> Unit)? = null, func2: ((Error) -> Unit)? = null): Fetch

这将使您可以像在Kotlin中一样调用它

fixedFetch.enqueue(requests, { println(it) }, { Timber.w(it) })

缺点是,由于Kotlin使用其Function1接口表示函数参数,因此它为库的Java用户提供了一种看起来很奇怪的方法。您还必须返回Unit.INSTANCE,因为这实际上是Kotlin中的一种类型。

Fetch enqueue(List<? extends Request>, Function1<? super List<? extends Request>, Unit>, Function1<? super Error, Unit>)