ContentProvider mHelper保持为空

时间:2016-06-22 13:45:30

标签: java android nullpointerexception android-contentprovider android-context

在我的代码中,我有一个自定义的ContentProvider类,可以在这里看到:

public class MaiMobileProvider extends ContentProvider {


    protected MaiMobileDbHelper mHelper;
    protected UriMatcher mMatcher = buildUriMatcher();
    //region code return on UriMatcher
    public static final int GNR_CODE = 1;
    public static final int PSP_CODE = 2;
    public static final int SERVICES_CODE = 3;
    public static final int HIGHLIGHT_CODE = 4;

    //endregion


    static UriMatcher buildUriMatcher() {
        // 1) The code passed into the constructor represents the code to return for the root
        // URI.  It's common to use NO_MATCH as the code for this case. Add the constructor below.
        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        final String authority = MaiMobileContract.CONTENT_AUTHORITY;

        // 2) Use the addURI function to match each of the types.  Use the constants from
        // WeatherContract to help define the types to the UriMatcher.
        matcher.addURI(authority, MaiMobileContract.PATH_GNR, GNR_CODE);
        matcher.addURI(authority, MaiMobileContract.PATH_PSP, PSP_CODE);
        matcher.addURI(authority, MaiMobileContract.PATH_SERVICES, SERVICES_CODE);
        matcher.addURI(authority, MaiMobileContract.PATH_SERVICES, HIGHLIGHT_CODE);

        // 3) Return the new matcher!
        return matcher;
    }

    //region Selections
    //services.isHighlighted = 1
    private static final String sServicesIsHighlightedSelection =
            MaiMobileContract.ServicesEntry.TABLE_NAME +
                    "." + MaiMobileContract.ServicesEntry.COLUMN_IS_HIGHLIGHTED + " = 1 ";


    //endregion

    //region custom cursors


    protected Cursor getHighlightedServices(Uri uri, String[] projection, String sortOrder) {
        boolean isHighlighted = MaiMobileContract.ServicesEntry.isServiceHighlighted(uri);
        String selection = null;

        if (isHighlighted)
            selection = sServicesIsHighlightedSelection;


        return mHelper.getReadableDatabase().query(
                MaiMobileContract.ServicesEntry.TABLE_NAME,
                projection,
                selection,
                null,
                null,
                null,
                sortOrder);
    }


    //endregion

    @Override
    public boolean onCreate() {
        mHelper = new MaiMobileDbHelper(getContext());
        return (mHelper == null) ? false : true;
    }


    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor mCursor;

        switch (mMatcher.match(uri)) {
            case GNR_CODE:
                mCursor = mHelper.getReadableDatabase().query(
                        MaiMobileContract.GnrEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;
            case PSP_CODE:
                mCursor = mHelper.getReadableDatabase().query(
                        MaiMobileContract.PspEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;
            case SERVICES_CODE:
                mCursor = mHelper.getReadableDatabase().query(
                        MaiMobileContract.ServicesEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;
            case HIGHLIGHT_CODE:
                mCursor = getHighlightedServices(uri, projection, sortOrder);
                break;
            default:
                throw new UnsupportedOperationException("Unknow uri: " + uri);
        }
        mCursor.setNotificationUri(getContext().getContentResolver(), uri);
        return mCursor;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        final int match = mMatcher.match(uri);

        switch (match) {

            case GNR_CODE:
                return MaiMobileContract.GnrEntry.CONTENT_TYPE;
            case PSP_CODE:
                return MaiMobileContract.PspEntry.CONTENT_TYPE;
            case SERVICES_CODE:
                return MaiMobileContract.ServicesEntry.CONTENT_TYPE;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        final SQLiteDatabase db = mHelper.getWritableDatabase();
        final int match = mMatcher.match(uri);
        Uri returnedUri;
        switch (match) {
            case GNR_CODE: {
                long id = db.insert(MaiMobileContract.GnrEntry.TABLE_NAME, null, values);
                if (id > 0)
                    returnedUri = MaiMobileContract.GnrEntry.buildGnrUri(id);
                else
                    throw new android.database.SQLException("Failed to insert row into " + uri);
                break;
            }
            case PSP_CODE: {
                long id = db.insert(MaiMobileContract.PspEntry.TABLE_NAME, null, values);
                if (id > 0)
                    returnedUri = MaiMobileContract.PspEntry.buildPspUri(id);
                else
                    throw new android.database.SQLException("Failed to insert row into " + uri);
                break;
            }
            case SERVICES_CODE: {
                long id = db.insert(MaiMobileContract.ServicesEntry.TABLE_NAME, null, values);
                if (id > 0)
                    returnedUri = MaiMobileContract.ServicesEntry.buildServicesUri(id);
                else
                    throw new android.database.SQLException("Failed to insert row into " + uri);
                break;
            }
            case HIGHLIGHT_CODE: {
                long id = db.insert(MaiMobileContract.ServicesEntry.TABLE_NAME, null, values);
                if (id > 0)
                    returnedUri = MaiMobileContract.ServicesEntry.buildServicesUri(id);
                else
                    throw new android.database.SQLException("Failed to insert row into " + uri);
                break;
            }
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return returnedUri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {

        final SQLiteDatabase db = mHelper.getWritableDatabase();


        // Student: Use the uriMatcher to match the WEATHER and LOCATION URI's we are going to
        final int match = mMatcher.match(uri);
        int rowsDeleted;
        // handle.  If it doesn't match these, throw an UnsupportedOperationException.
        if (null == selection)
            selection = "1";
        switch (match) {
            case GNR_CODE:
                rowsDeleted = db.delete(MaiMobileContract.GnrEntry.TABLE_NAME, selection,
                        selectionArgs);
                break;
            case PSP_CODE:
                rowsDeleted = db.delete(MaiMobileContract.PspEntry.TABLE_NAME, selection,
                        selectionArgs);
                break;
            case SERVICES_CODE:
                rowsDeleted = db.delete(MaiMobileContract.ServicesEntry.TABLE_NAME, selection,
                        selectionArgs);
                break;
            case HIGHLIGHT_CODE:
                rowsDeleted = db.delete(MaiMobileContract.ServicesEntry.TABLE_NAME, selection,
                        selectionArgs);
                break;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
        if (rowsDeleted != 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return rowsDeleted;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

        final SQLiteDatabase db = mHelper.getWritableDatabase();
        final int match = mMatcher.match(uri);
        int updatedRows;

        switch (match) {
            case GNR_CODE:
                updatedRows = db.update(MaiMobileContract.GnrEntry.TABLE_NAME, values, selection,
                        selectionArgs);
                break;
            case PSP_CODE:
                updatedRows = db.update(MaiMobileContract.PspEntry.TABLE_NAME, values, selection,
                        selectionArgs);
                break;
            case SERVICES_CODE:
                updatedRows = db.update(MaiMobileContract.ServicesEntry.TABLE_NAME, values, selection,
                        selectionArgs);
                break;
            case HIGHLIGHT_CODE:
                updatedRows = db.update(MaiMobileContract.ServicesEntry.TABLE_NAME, values, selection,
                        selectionArgs);
                break;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
        if (updatedRows != 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }

        return updatedRows;
    }


    @Override
    @TargetApi(11)
    public void shutdown() {
        mHelper.close();
        super.shutdown();
    }
}

此提供程序用于请求我用于制作地图标记的方法,并最终将它们添加到ClusterManager中,可以在此处看到:

public class BaseMapFragment extends SupportMapFragment  {


    //region Parameters
    private final String LOG_TAG = "BaseMapFragment";
    public static int layout;
    protected FetchDataInterface mApiGson;
    protected GoogleMap gMap;
    protected SecurityMapFragment mapFragment;
    protected MaiMobileProvider mProvider;

    protected List<MaiClusterItem> pspItems = new ArrayList<>();
    protected List<MaiClusterItem> gnrItems = new ArrayList<>();
    protected ClusterManager<MaiClusterItem> mClusterManager;
    //endregion


    //region Methods

    protected void addMapMarkers(MaiMobileProvider provider, String markerGroup) {
        switch (markerGroup) {//between a switch and a if statement, I adopted the switch for future implementations
            case "psp":{
                Cursor cursor = provider.query(MaiMobileContract.PspEntry.CONTENT_URI,null,null,null,MaiMobileContract.PspEntry.COLUMN_DISTANCE +" ASC");
                cursor.moveToFirst();
                Log.v("Cursor psp: ", cursor.toString());
                Log.v("Cursor psp ", "has: " + cursor.getCount());

                while(cursor.moveToNext()){
                //cyclic add items to each MaiClusterItem List
                    LatLng coco = new LatLng(
                            cursor.getDouble(ColumnIndexes.PspIndexes.COLUMN_COORD_LAT),
                            cursor.getDouble(ColumnIndexes.PspIndexes.COLUMN_COORD_LONG));
                    pspItems.add(new MaiClusterItem(coco,
                            BitmapDescriptorFactory.fromResource(R.mipmap.psp),
                            cursor.getString(ColumnIndexes.PspIndexes.COLUMN_NAME),
                            cursor.getString(ColumnIndexes.PspIndexes.COLUMN_DESCRIPTION)));
                    Log.v("pspItems ", "has: " + pspItems.size());
                }
                cursor.close();
                break;
            }

            case "gnr": {
                Cursor cursor = provider.query(MaiMobileContract.GnrEntry.CONTENT_URI, null, null, null, MaiMobileContract.GnrEntry.COLUMN_DISTANCE + " ASC");
                cursor.moveToFirst();
                Log.v("Cursor gnr: ", cursor.toString());
                while(cursor.moveToNext()){
                    LatLng coco = new LatLng(
                            cursor.getDouble(ColumnIndexes.GnrIndexes.COLUMN_COORD_LAT),
                            cursor.getDouble(ColumnIndexes.GnrIndexes.COLUMN_COORD_LONG));
                    gnrItems.add(new MaiClusterItem(
                            coco,
                            BitmapDescriptorFactory.fromResource(R.mipmap.gnr_green),
                            cursor.getString(ColumnIndexes.GnrIndexes.COLUMN_NAME),
                            ""));
                    Log.v("gnrItems ", "has: " + gnrItems.size());
                }
                cursor.close();
                break;
            }
            default:
                throw new UnsupportedOperationException("Unknown error adding markers: " + getContext() + " at " + LOG_TAG);
        }
    }
    //region PspData Call

    protected void makePspMarkers() {
        addMapMarkers(mProvider, "psp");
        mClusterManager.addItems(pspItems);
        mClusterManager.setRenderer(new MaiClusterItem.ClusterItemRenderer(getActivity(), gMap, mClusterManager));

    }
    //endregion


    //region GnrData Call
    protected void makeGnrMarkers() {
        addMapMarkers(mProvider, "gnr");
        mClusterManager.addItems(gnrItems);
        mClusterManager.setRenderer(new MaiClusterItem.ClusterItemRenderer(getActivity(), gMap, mClusterManager));

    }
    //endregion


    //endregion
}

并且此BaseMapFragment在SecurityMapFragment类上进行了扩展:

public class SecurityMapFragment extends BaseMapFragment implements
        OnMapReadyCallback {


    //region Properties
    public CameraPosition userCameraPosition;
    //endregion


    //region Methods


    //region MapReady
    @Override
    public void onMapReady(GoogleMap googleMap) {
        gMap = googleMap;


        //region map design
        gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        gMap.getUiSettings().setZoomControlsEnabled(false);
        gMap.setMyLocationEnabled(true);
        gMap.getUiSettings().setMyLocationButtonEnabled(false);
        //endregion


        //region camera+clustering
        userCameraPosition =
                new CameraPosition.Builder()
                        .target(MainActivity.userCoords)
                        .zoom(9f)
                        .bearing(-10f)
                        .build();

        gMap.moveCamera(CameraUpdateFactory.newCameraPosition(userCameraPosition));//set camera on user position (static for now)
        mClusterManager = new ClusterManager<>(getContext(), gMap);
        gMap.setOnCameraChangeListener(mClusterManager);//cluster call
        //endregion
    }
    //endregion


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mProvider = new MaiMobileProvider();

        //generate map
        mapFragment = (SecurityMapFragment) this.getFragmentManager().findFragmentById(R.id.security_map_view);
        getMapAsync(this);

        //interface api instance for Gson
        mApiGson = RetrofitUtils.createGsonRetrofitInterface();
        makePspGnrMarkers();//this will be called on created and also on filter selection


    }


    //region Add markers methods
    private void makePspGnrMarkers() {
        //Todo mClusterManager.clearItems();
        makePspMarkers();
        makeGnrMarkers();
    }

    //endregion


    //endregion
}

MainActivity调用SecurityMapFragment,然后在片段上调用它来使用在我的服务上创建的数据库中的数据的方法。 现在出现了问题,由于某些原因,在执行mHelper.getReadableDatabase().query(...);时,它在该方法调用上给了NullPointerException,这发生在MaiMobileProvider方法的.query()上,这是BaseMapFragment用于获取数据库数据的方法。 我知道mHelpernull,我不知道是为什么。 mHelper的内部化是在提供者的onCreate上进行的。

注意:是的,我的提供者正在<application>

内的清单上宣布
<provider
    android:name=".data.database.MaiMobileProvider"
    android:authorities="pt.gov.mai.mobile.android"
    android:exported="false" />

提前感谢大家的阅读和见解。

1 个答案:

答案 0 :(得分:0)

就像Selvin说我应该使用ContentResolver.query()因为应用程序已经负责实例化清单中的Provider。 因此,作为“改变了什么”的一部分:

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mResolver = getContext().getContentResolver();//From a Provider to a ContentResolver
    //generate map
    mapFragment = (SecurityMapFragment) this.getFragmentManager().findFragmentById(R.id.security_map_view);
    getMapAsync(this);

    //interface api instance for Gson
    mApiGson = RetrofitUtils.createGsonRetrofitInterface();
    makePspGnrMarkers();//this will be called on created and also on filter selection


}

然后我们从我们的上下文中获取ContentResolver之后,我们可以使用它来查询我们的提供程序,就像它完成一样。 还必须参考Selvin,评论我的问题并指出应该使用Resolver。 还有Android documentation on ContentProvider and ContentResolver