Inyectar base de datos en un ContentProvider con daga

Quiero inyectar un singleton SqliteOpenHelper en un ContentProvider . Sin embargo, parece que la instancia de ContentProvider se está creando antes de que se cree la instancia de aplicación ( getApplicationContext() devuelve null). ¿Cuándo puedo inyectar la base de datos? He intentado en el constructor y en el método onCreate() del ContentProvider .

Me enfrenté al mismo problema y tuve que aplazar la inyección hasta que la base de datos se necesitaba. Es posible que pueda usar la inyección perezosa de Dagger para lograr el mismo efecto.

De la documentación onCreate del proveedor de contenido :

Debe aplazar la inicialización no trivial (como abrir, actualizar y escanear bases de datos) hasta que se utilice el proveedor de contenido

Al parecer esta sugerencia no puede ser ignorada. La implementación del método onCreate () proporciona un ejemplo usando un SQLiteOpenHelper con un proveedor de contenido.

Como Alex Baker señaló, la solución del problema es aplazar la inyección cuando se llama por primera vez una operación (consulta, insertar, actualizar, eliminar).

Para dar un ejemplo:

Esto no funcionará:

 public class YourProviderNull extends ContentProvider { @Inject YourSQLHelper yourHelper; @Override public boolean onCreate() { YourActivity.getComponent().inject(this); //NPE!!! //other logic return true; } @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = yourHelper.getReadableDatabase(); //other logic } @Override public Uri insert(@NonNull Uri uri, ContentValues values) { SQLiteDatabase db = yourHelper.getWritableDatabase(); //other logic } @Override public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = yourHelper.getWritableDatabase(); //other logic } @Override public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = yourHelper.getWritableDatabase(); //other logicreturn db.update(resolveTableNameForUri(uri), values, selection, selectionArgs); } 

}

Pero esto funcionará correctamente:

 public class YourProviderWorking extends ContentProvider { @Inject YourSQLHelper yourHelper; @Override public boolean onCreate() { //other logic return true; } @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if(yourHelper == null){ deferInit(); } SQLiteDatabase db = yourHelper.getReadableDatabase(); //other logic } @Override public Uri insert(@NonNull Uri uri, ContentValues values) { if(yourHelper == null){ deferInit(); } SQLiteDatabase db = yourHelper.getWritableDatabase(); //other logic } @Override public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { if(yourHelper == null){ deferInit(); } SQLiteDatabase db = yourHelper.getWritableDatabase(); //other logic } @Override public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) { if(yourHelper == null){ deferInit(); } SQLiteDatabase db = yourHelper.getWritableDatabase(); //other logicreturn db.update(resolveTableNameForUri(uri), values, selection, selectionArgs); } private void deferInit(){ YourActivity.getComponent().inject(this); } 

}

Solución sencilla

Hay una razón simple para esto, el proveedor onCreate() se llama antes del método apropiado en la aplicación. Puede crear un componente en otro método de la aplicación, por ejemplo, attachBaseContext .


1 Mueva su lógica de onCreate a attachBaseContext en su aplicación.

 @Override public void attachBaseContext(Context base){ super.attachBaseContext(base); mApplicationComponent = DaggerApplicationComponent.builder() .applicationModule(new ApplicationModule(this)) .build(); mApplicationComponent.inject(this); } 

2 Ahora puede inject en OnCreate en su ContentProvider:

 public boolean onCreate() { YourMainApplication.get(getContext()).getComponent().inject(this); return true; } 

Descargo de responsabilidad: Créditos completos a @LeEnot de este blog ruso: Dagger2 Inject in Content Provider . La respuesta aparece aquí por conveniencia, ya que no está disponible en inglés.

  • Utilice los módulos Dagger sin la directiva "inyecta"
  • Cómo inyectar una actividad en un adaptador usando dagger2
  • ¿Puedo extender una aplicación personalizada en Espresso?
  • Dagger2 dagger.android. * Las clases no existen
  • Dagger2 Component (un-scoped) no puede depender de los componentes del ámbito - Error
  • Dagger código que da NoClassDefFoundError en las pruebas de instrumentación de Android, pero funciona en la aplicación normal
  • ¿Es posible usar Dagger en el proyecto de la biblioteca?
  • Dagger - android.app.IntentService con @Inject
  • No se puede proporcionar sin un constructor @Inject o de un método @ Proporcionado-anotado
  • Java.lang.NoClassDefFound usando Dagger 2 para Android 4
  • Cómo usar daga en un proyecto de biblioteca de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.