У меня проблема после преобразования Java в Kotlin с ошибкой в ​​Android Studio. Невозможно определить тип для этого параметра. - PullRequest
0 голосов
/ 13 октября 2018

Когда я преобразовал этот метод в 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, где значения updatedRequests и error говорят: Cannot infer a type for this parameter.

Итак, я нажму hover на метод и нажму 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 голосов
/ 14 октября 2018

TLDR: синтаксис сокращений в вашем конкретном случае:

fetch.enqueue(requests, Func { updatedRequests ->

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

Проблема здесь в том, что вы вызываете функцию, написанную на Kotlin.Вы не можете использовать короткий лямбда-синтаксис здесь, так как Kotlin не будет автоматически превращать лямбды в правильный интерфейс.

"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+) вы можете использовать лямбды в обоих случаях

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

Это немного сбивает с толку.В настоящее время API-интерфейсы, написанные на Kotlin, предназначенные для потребления Kotlin, должны использовать не функциональные интерфейсы, а фактические параметры функции, то есть для функции 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) })

Недостатком является то, что это дает довольно странный метод для пользователей библиотеки Java, поскольку Kotlin использует его Function1 интерфейс для представления параметров функции.Вам также придется вернуть Unit.INSTANCE, так как на самом деле это тип в Kotlin.

Fetch enqueue(List<? extends Request>, Function1<? super List<? extends Request>, Unit>, Function1<? super Error, Unit>)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...