简体   繁体   English

kotlin 函数返回 null

[英]kotlin function returning null

I am trying some android development with kotlin.我正在尝试使用 kotlin 进行一些 android 开发。 In my case I want to overwrite: ContentProvider where I have to overwrite the function "query".在我的情况下,我想覆盖:ContentProvider,我必须覆盖函数“查询”。 "query" returns "Cursor" type. “查询”返回“光标”类型。 However, when I create the Cursor instance in the function with database.query I get back a "Cursor?"但是,当我使用 database.query 在函数中创建 Cursor 实例时,我会得到一个“Cursor?” type.类型。 So I can only return Cursor if it is not null, but what do I do if it is null?所以我只能返回 Cursor 如果它不为空,但如果它为空我该怎么办?

This is what it basically looks like:这是它的基本外观:

override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor {

    val cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder)
            // make sure that potential listeners are getting notified
            cursor?.setNotificationUri(getContext()?.getContentResolver(), uri)

            if(cursor != null)
                return cursor
            else
                // what to do here?

Any Ideas how to solve that?任何想法如何解决这个问题?

Thanks, Sven谢谢,斯文

UPDATE First of all thanks for the answers.更新首先感谢您的回答。

Annotation seems not to work in my case as I can only access the compiled code and I dont get the option to annotate the source.在我的情况下,注释似乎不起作用,因为我只能访问已编译的代码,而我没有选择注释源代码。 Maybe I am missing something here.也许我在这里遗漏了一些东西。

Implementing my own cursor Seems like overkill especially if I have to do it every time that problem occurs.实现我自己的光标似乎有点矫枉过正,尤其是如果每次出现问题时我都必须这样做。

So it seems my only option is to return cursor!!所以看来我唯一的选择是返回光标!! But I dont know how exactly to do it.但我不知道该怎么做。 My code is a bit more complicated than in my example, I missed a when statement.我的代码比我的例子复杂一点,我错过了一个 when 语句。 This is an updated version:这是一个更新的版本:

override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor {

    val cursor = ??? //how to initialize cursor somehow?
    val db = database.getWritableDatabase()

    if(db != null) {
        val cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder)
                // make sure that potential listeners are getting notified
                cursor?.setNotificationUri(getContext()?.getContentResolver(), uri)

                if(cursor != null)
                    return cursor
     }

    // return what here? cursor does not exist
}

Do I really have to implement my own cursor and clutter my code with useless "throw UnsupportedExceptions"?我真的必须实现我自己的游标并用无用的“throw UnsupportedExceptions”来弄乱我的代码吗?

Your options are:您的选择是:

  • If cursor is null , throw an exception: return cursor!!如果cursornull ,则抛出异常: return cursor!! (this is OK in case you are sure that cursor is never actually null (这是可以的,以防您确定cursor实际上从未为null
  • If cursor is null , return some trivial cursor (eg your own implementation of AbstractCursor that behaves as an empty result set如果cursornull ,则返回一些简单的游标(例如,您自己的AbstractCursor实现,它表现为空结果集
  • (as Franck said in his comment) annotate QueryBuilder.query() function as @NotNull : http://blog.jetbrains.com/kotlin/using-external-annotations/ (正如 Franck 在他的评论中所说)将QueryBuilder.query()函数注释为@NotNullhttp : QueryBuilder.query()

There are libraries built around this topic:有围绕这个主题构建的库:

The Result library for Kotlin gives a nice way to handle your case of "do this, or that" based on response values. Kotlin 的Result库提供了一种很好的方法来处理基于响应值的“做这个或那个”的情况。 And to have a real response and an exception or invalid response which is what you are seeking.并获得真正的响应和异常或无效的响应,这正是您所寻求的。

For Promises, you can find the same thing in the Kovenant library.对于 Promises,您可以在Kovenant库中找到相同的内容 With Kovenant promises can be resolved immediately and do not have to be async.使用 Kovenant 承诺可以立即解决,而不必是异步的。 So it works as a general purpose "I have a result, or not" library.所以它作为一个通用的“我有一个结果,或者没有”库。

// ... in my function that returns Promise<Cursor, String>
if (good) {
   return Promise.ofSuccess<Cursor, String>(cursor)
}
else {
   return Promise.ofFail<Cursor, String>("no database connection")
}

Then in the caller of the function:然后在函数的调用者中:

myFuncMakingACursor() success { cursor ->
    //called when all is ok, and I have a cursor
} fail {
    //called when promise is rejected
} always {
    //no matter what result we get, this is always called once.
}

Promises do not always have to have errors as the failure type. Promise 并不总是必须将错误作为失败类型。 They can be anything you want.它们可以是您想要的任何东西。 An error code, error message, data class, or an exception if you wish.错误代码、错误消息、数据类或异常(如果您愿意)。

Both of these libraries give you manner for returning alternative results from a single function, and also for branching the code based on the results这两个库都为您提供了从单个函数返回替代结果以及基于结果分支代码的方式

These are good Kotlin alternatives to Optional and Maybe .这些是OptionalMaybe Kotlin 很好的替代品。

It is also fine to use nulls, and there are many operators that help to deal with null values in these cases.使用空值也很好,在这些情况下,有许多运算符可以帮助处理空值。 In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them is another SO post covering nullability in general explaining some of the operators available (including the "safe call" operator used in some of the answers here).在 Kotlin 中,处理可空值、引用或转换它们的惯用方法是什么是另一篇涵盖可空性的 SO 帖子,一般解释了一些可用的运算符(包括此处某些答案中使用的“安全调用”运算符)。

if (db != null){
    //...
} else {
    return null
}

and put return type to Cursor?并将返回类型设置为 Cursor?

That is how i do usually.这就是我通常的做法。 Don't know if it is bad or good.不知道是好是坏。

may be you can update function end : Cursor to : Cursor?也许你可以将函数 end : Cursor 更新为 : Cursor? example:例子:

override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {}

There's a hack actually that allows you to trick the Kotlin compiler into accepting null as a non-nullable reference.实际上有一个 hack 可以让你欺骗 Kotlin 编译器接受null作为不可为空的引用。

NullHack.java : NullHack.java :

public class NullHack {
    private NullHack() {
    }

    @SuppressWarnings("ConstantConditions")
    @NotNull
    public static <T> T nullHack(@Nullable T object) {
        return object;
    }
}

NullHack.kt :空黑客.kt :

fun <T> T?.nullHack(): T = NullHack.nullHack(this)

Then in the ContentProvider subclass you can write the following code:然后在ContentProvider子类中,您可以编写以下代码:

override fun query(uri: Uri, projection: Array<out String>?, selection: String?,
        selectionArgs: Array<out String>?, sortOrder: String?): Cursor {

    val db = database.getWritableDatabase()!!
    val cursor = queryBuilder.query(db, projection, selection, selectionArgs,
            null, null, sortOrder)
    // make sure that potential listeners are getting notified
    cursor?.setNotificationUri(getContext()?.getContentResolver(), uri)
    return cursor.nullHack()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM