Объясните эту основную функцию Котлина - PullRequest
0 голосов
/ 06 декабря 2018

Я новичок в Java / Kotlin и работаю с этим учебным пособием , чтобы создать приложение для Android с виджетом, который может запрашивать JSON из URL-адреса и отображать результаты.

Меня смущает последний пример кода:

val service = ServiceVolley()
val apiController = APIController(service)

val path = "example_endpoint"
val params = JSONObject()
params.put("email", "foo@email.com")
params.put("password", "barpass")

apiController.post(path, params) { response ->
    // Parse the result
}

Как обычно в Kotlin, если последний параметр функции является функцией (и вы передаете лямбда-выражение в качестве соответствующего аргумента), вы можете указать его вне скобок, как мы уже делали выше - одна из маленьких причуд, которые мне нравятся в Kotlin.

В моем коде виджета у меня есть вспомогательная функция updateAppWidget, в которой яиспользуйте приведенный выше код и можете успешно запросить API, однако я получил большую часть кода, который был в updateAppWidget функции внутри { response -> // Parse the result } блока:

apiController.post(path,params) { response ->
    // Get 'bar' from the response which is {'foo':'bar'}
    val widgetText = response?.get(response.names().getString(0)).toString() 

    // Construct the RemoteViews object
    val views = RemoteViews(context.packageName, R.layout.statusr)
    views.setTextViewText(R.id.appwidget_text, widgetText)

    // Instruct the widget manager to update the widget
    appWidgetManager.updateAppWidget(appWidgetId, views)
}

Может ли кто-нибудь объяснить значение последних 3 строк кодового блока first и сказать мне, как я мог бы написать это, чтобы поднять логику на один уровень, и стоит ли это того?

НемедленноПроблема, которую я заметил, заключается в том, что я не могу ссылаться на widgetText без этого блока.

РЕДАКТИРОВАТЬ для ясности

Я думаю, что у меня над головой.Дальнейшее чтение предполагает, что я передаю лямбду, используя -> ???Я думаю, что я действительно хочу сделать:

Получить вызов apiController.post из кода виджета полностью, поэтому у меня это теперь в отдельном классе:

class GetData {

    fun widget_text(){
        val service = ServiceVolley()
        val apiController = APIController(service)

        val path = "endpoint"
        val params = JSONObject()

        params.put("some", "data")

        apiController.post(path, params) { response ->
            val widgetText = response?.get(response.names().getString(0)).toString() 
        }
    }
}

Будетхотелось бы иметь возможность вызывать что-то вроде GetData.widget_text() изнутри updateAppWidget, но я вернулся к своей первоначальной проблеме: как сделать widgetText доступным вне apiController.post(path,params) { response -> // Logic }} и вернуть это.

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

Значение первых трех последних строк: данные в параметрах передаются некоторому типу бэкэнда (сервера).

apiController.post(path, params) { response ->
    val widgetText = response?.get(response.names().getString(0)).toString() 
    // Display the result in the App Widget
}

Запрос выполняется асинхронно.Это означает, что код в лямбда-выражении будет выполняться после поступления ответа от сервера, в то время как пользовательский интерфейс приложения будет оставаться активным.Метод, запустивший внутренний вызов, завершится (если ему пришлось ждать, пока ответ не поступил в пользовательском интерфейсе, он может зависнуть).

Возможная структура приложения, использующая GetData в качестве класса, который управляет внутренним вызовом.:

class GetData {
    interface WidgetTextCallback {
        fun onTextLoaded(text: String)
    }

    companion object {
        fun widget_text(callback: WidgetTextCallback) {
            val service = ServiceVolley()
            val apiController = APIController(service)

            val path = "endpoint"
            val params = JSONObject()

            params.put("some", "data")

            apiController.post(path, params) { response ->
                val widgetText = response?.get(response.names().getString(0)).toString()
                callback.onTextLoaded(widgetText)
            }
        }
    }
}

И использовать интерфейс для получения текста виджета:

class NewAppWidget : AppWidgetProvider() {

    override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {

        GetData.widget_text(object: GetData.WidgetTextCallback{
            override fun onTextLoaded(widgetText: String) {
                // There may be multiple widgets active, so update all of them
                for (appWidgetId in appWidgetIds) {
                    updateAppWidget(context, widgetText, appWidgetManager, appWidgetId)
                }
            }
        })
    }

    companion object {

        internal fun updateAppWidget(context: Context, widgetText: String, appWidgetManager: AppWidgetManager,
                                     appWidgetId: Int) {
            // Construct the RemoteViews object
            val views = RemoteViews(context.packageName, R.layout.new_app_widget)
            views.setTextViewText(R.id.appwidget_text, widgetText)

            // Instruct the widget manager to update the widget
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}
0 голосов
/ 07 декабря 2018

«поднимите эту логику на один уровень» звучит так, как будто вы хотите обработать ответ где-то еще в вашем коде.Почему бы вам просто не передать его в функцию-обработчик?

fun handleResponse(response: Type?) {
    // Parse the result
}

apiController.post(path, params) { response ->
    handleResponse(response)
}

или короче:

apiController.post(path, params) { handleResponse(it) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...