首页 > 解决方案 > 解释这个基本的 Kotlin 函数

问题描述

我是 Java/Kotlin 的新手,正在通过本教程构建一个带有小部件的 Android 应用程序,该小部件可以从 URL 查询一些 JSON 并呈现所述结果。

我对最后一个代码示例感到困惑:

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 中一样,如果函数的最后一个参数是一个函数(并且您将 lambda 表达式作为相应的参数传递),您可以在括号之外指定它,就像我们在上面所做的那样 - 一个小怪癖我喜欢 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 行的重要性,并告诉我如何编写它以将逻辑提升一个级别,这是否值得?

我注意到的直接问题是我不能在这个块之外引用 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 }}并返回它。

标签: androidkotlin

解决方案


前三行的含义:params中的数据被传递到某种类型的后端(服务器)。

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

请求是异步执行的。这意味着,lambda 表达式中的代码将在服务器响应后运行,而应用程序的 UI 将保持可点击状态。启动后端调用的方法将完成(如果它必须等到 UI 中的响应可能会冻结)。

一个可能的应用程序结构,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)
        }
    }
}

推荐阅读