-2

в моем коде у меня есть свой собственный класс ContentProvider, который можно увидеть здесь:ContentProvider mHelper остается нулевой

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

'new MaiMobileProvider();' это не то, как мы используем 'ContentProviders' ... даже если ... как вы думаете, что' onCreate' будет называться автоматически? ... вам нужно использовать 'ContentResolver.query' – Selvin

+0

, я бы так подумал, да, черт возьми, я буду называть' onCreate' вручную и видеть. Спасибо. – diomonogatari

+2

NOOOOOOOOOOOOOO !!!! вам нужно использовать 'ContentResolver.query' вместо прямого вызова' MaiMobileProvider.query' ... тогда ОС Android создаст экземпляр вашего 'MaiMobileProvider' (если власти совпадут) и вызовет' onCreate', и все будет просто отлично – Selvin

ответ

0

Как и Selvin, я должен использовать ContentResolver.query(), потому что приложение уже отвечает за создание экземпляра Провайдера, который находится в манифесте. Так как часть «что изменилось»:

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 из нашего контекста мы можем использовать его для запроса нашего поставщика, так же, как это было сделано. Также нужно обратиться к Сельвину, который прокомментировал мой вопрос и указал, что следует использовать Resolver. А также Android documentation on ContentProvider and ContentResolver.

Смежные вопросы