安卓:getContext().getContentResolver() 有时会出现 NullPointerException。

12
我想问一下为什么我们会得到这个注释:

Method invocation getContext.getContentResolver() may produce NullPointerException

为什么它出现在这里而不是程序的其他部分(如Fragment/Activity)?Google的教程中使用了这种方法,这是ContentProvider代码的链接:https://github.com/udacity/Sunshine-Version-2/blob/sunshine_master/app/src/main/java/com/example/android/sunshine/app/data/WeatherProvider.java 即使你只创建一个空白活动并将该方法放在新创建的ContentProvider中,它也会出现在那里。
我们应该在ContentProvider之外使用 getContext().getContentResolver().notifyChange(uri, null);,然后在更新/插入/删除完成后通知更改吗?还是有其他修复方法?

如果你的IDE提示getContext()可能返回null,那么getContext().getContentResolver()就会导致NullPointerException,这只是一个简单的警告。 - Tom
6个回答

9
如果你查看ContentProvider的源代码(只需在Android Studio中点击类名并按住SHIFT),你会发现实现是将一个Context类型的对象作为mContext保存的。
你的解决方案与此相同,这意味着如果ContentProvider的mContext为空,你的引用也将为空。所以这是没有必要的。
为了帮助你,这只是你的IDE警告自己构建这样的结构。但在这种情况下,始终会有上下文,因为ContentProvider是由您的系统生成的。为了避免IDE中的错误,请在类定义上方写上@SuppressWarnings("ConstantConditions"),如下所示:
...
@SuppressWarnings("ConstantConditions")
public class NoteProvider extends ContentProvider {
...

1
忽略整个类别的这种警告是一个非常糟糕的想法,至少在那行代码之前应该使用像 //noinspection ConstantConditions 这样的东西 - 这只会关闭下一行代码的警告。 - maresmar

8
如果您能确保getContext()永远不会是null,那么您可以简单地忽略此警告。我认为如果您只检查null,甚至可以消除该警告:
if (getContext() != null) {
    getContext().getContentResolver();
}

请记住,如果getContext()null,则不会执行代码。

祝好

编辑: 要小心@Shivani Gupta给你的答案,因为你可能会得到不同的上下文。请参见:getContext()、getApplicationContext()、getBaseContext()和"this"之间的区别


3

请使用getApplicationContext().getContentResolver()方法。


1
我只能使用“getContext().getApplicationContext().getContentResolver();”,而且“getContext().getApplicationContext()”部分产生了相同的结果。 - Radek O

1
根据ContentProvider getContext()文档,该方法检索此提供程序正在其中运行的上下文。只有在调用onCreate()之后才可用--在构造函数中将返回null。因此,在insert()update()delete()中,getContext()方法不会返回null,因为这些调用之前将调用onCreate()。因此,如果您在这种情况下使用它,则可以禁用该行的警告...
//noinspection ConstantConditions
getContext().getContentResolver().notifyChange(uri, null);

1

好的,看起来我通过在类的开头声明Context自己解决了它。

public class NoteProvider extends ContentProvider {
    Context context;

然后在 onCreate() 中初始化它。保留 HTML,不解释。
@Override
    public boolean onCreate() {
        mSQLiteOpenHelper = new NoteDbHelper(getContext());
        context = getContext();

        return true;
    }

我认为这样做可以确保在使用insert/update/delete/query方法时,当我使用context.getContentResolver().notifyChange(uri, null);retCursor.setNotificationUri(context.getContentResolver(), uri);时,我总是有上下文 - retCursor是这些方法返回的游标。

我已经在我的手机上运行了应用程序,目前还没有问题,但如果有问题,可能会对此帖子进行编辑。

编辑:

毕竟这没有什么区别 - 感谢@Mate的答案解释,谢谢,我现在明白了:]


1
你的解决方案只是欺骗了IDE,getContext会给你一个对ContentProvider的mContext的引用,如果这个引用为空,那么你的上下文也将为空。但不用担心,它不可能为空,看看我的答案就知道了。 - Mate

0
每当您尝试使用对象的成员或方法时,如果您尝试使用的成员/方法所属的对象为null,则可能会出现运行时异常。假设您想要使用对象obj的成员/方法。如果您像这样使用它:
if (obj != null) {
    //use members/methods of obj
}

那么,你已经成功地预防了这个问题。不过,你也许想把它作为一个异常来处理,就像这样:

try {
    //use members/methods of obj
} catch (NullPointerException npe) {
    //handle the NullPointerException
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接