Android: getContext().getContentResolver() 有时会出现 NullPointerException

Android: getContext().getContentResolver() sometimes gets NullPointerException

我想问一下为什么我们得到这个注解:

Method invocation getContext.getContentResolver() may produce NullPointerException

为什么它在那里而不是在程序的其他部分 Fragment/Activity?这种方法已在 Google 制作的教程中使用 - 这里是 link 用于 ContentProvider 代码 https://github.com/udacity/Sunshine-Version-2/blob/sunshine_master/app/src/main/java/com/example/android/sunshine/app/data/WeatherProvider.java 即使你创建一个只有空白 activity 的应用程序并将该方法放入一个新创建的 ContentProvider 就在那里。

我们是否应该在 ContentProvider 之外使用 getContext().getContentResolver().notifyChange(uri, null); 获取传递的 uri,然后在 update/insert/delete 完成 notifyChange 之后使用?或者我们可以用某种方式解决它?

getApplicationContext().getContentResolver() 希望这会奏效。

如果您可以确保 getContext() 永远不会 null 那么您可以简单地忽略此警告。我认为您的警告甚至消失了,只需检查 null:

if (getContext() != null) {
    getContext().getContentResolver();
}

您只需要记住,如果 getContext()null.[=12=,则不会执行代码]

干杯

编辑: 小心@Shivani Gupta 给你的答案,因为你可能会得到不同的上下文。参见:Difference between getContext() , getApplicationContext() , getBaseContext() and "this"

每当您尝试使用对象的成员或方法时,如果您尝试使用其 member/method 的对象为 null,则可能会出现运行时异常。假设您要使用对象 obj 的 member/method。如果你这样使用它:

if (obj != null) {
    //use members/methods of obj
}

那么你就避免了这个问题。但是,您可能希望将其作为异常处理,如下所示:

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

好吧,我似乎通过在 class.

的开头声明 Context 来自行修复它
public class NoteProvider extends ContentProvider {
    Context context;

然后在 onCreate()

中初始化它
@Override
    public boolean onCreate() {
        mSQLiteOpenHelper = new NoteDbHelper(getContext());
        context = getContext();

        return true;
    }

我认为这确保我在使用 context.getContentResolver().notifyChange(uri, null);[ 时始终有上下文=36=](context.getContentResolver(), uri); 在 insert/update/delete/query 方法中 - retCursor 被上述方法返回游标。

我 运行 我的 phone 上有应用程序,目前还没有问题,如果我愿意的话,可能会对此进行编辑 post。

编辑:

毕竟没有什么区别-@Mate 的回答中的解释,谢谢你,我想我现在明白了:]

如果您查看 ContentProvider 的源代码(只需按住 SHIFT 并单击 Android Studio 中的 class 名称),您会发现该实现持有一个 Context 类型的对象mContext.

你的解决方法是一样的,也就是说如果ContentProvider的mContext为null,那么你的reference也会为null。所以没有这个必要。

为了帮助您,这只是对您 IDE 如果您自己构建这样的结构的警告。但在这种情况下总会有上下文,因为 ContentProvider 是由您的系统生成的。为避免 IDE 中的错误,只需将 @SuppressWarnings("ConstantConditions") 写在 class 定义之上,例如:

...
@SuppressWarnings("ConstantConditions")
public class NoteProvider extends ContentProvider {
...

根据ContentProvider getContext() docs

Retrieves the Context this provider is running in. Only available once onCreate() has been called -- this will return null in the constructor.

因此 getContext() 方法在 insert()update()delete() 中不会 return null,因为 onCreate()将在这些调用之前被调用。

因此,如果您在这种情况下使用它,则可以禁用该行的警告...

//noinspection ConstantConditions
getContext().getContentResolver().notifyChange(uri, null);

当您在 Fragment 或 DialogFragment 中调用 getActivity()getContext() 以使用 getContentResolver() 等父 activity 方法之一时,通常会发生这种情况,因为编译器有疑问这些方法可能 return 一个空值。

解决这个问题,而不是使用getActivity()getContext();您可以简单地分别使用 requireActivity()requireContext();这些方法确保非空值是 returned.

你可以看看答案