Dagger 2 : error while getting a multiple instances of same object with @Named
How can I get multiple instances of the same type returned like a cursor
For example: –
Module
@CursorScope
public class CursorModule {
@Provides
Cursor provideSongCursor(
@Named("Song") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{
BaseColumns._ID,
MediaStore.Audio.AudioColumns.TITLE,
MediaStore.Audio.AudioColumns.ARTIST,
MediaStore.Audio.AudioColumns.ALBUM,
MediaStore.Audio.AudioColumns.DURATION
}, MediaStore.Audio.AudioColumns.IS_MUSIC + "=1", null, null);
}
@Provides
Cursor provideAlbumCursor(
@Named("Album") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{
BaseColumns._ID,
MediaStore.Audio.AlbumColumns.ALBUM,
MediaStore.Audio.AlbumColumns.ARTIST,
MediaStore.Audio.AlbumColumns.NUMBER_OF_SONGS,
MediaStore.Audio.AlbumColumns.FIRST_YEAR
}, null, null, null);
}
@Provides
Cursor provideArtistCursor(@Named("Artist") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
new String[] {
BaseColumns._ID,
MediaStore.Audio.ArtistColumns.ARTIST,
MediaStore.Audio.ArtistColumns.NUMBER_OF_ALBUMS,
MediaStore.Audio.ArtistColumns.NUMBER_OF_TRACKS
}, null, null,null);
}
@Provides
Cursor provideGenreCursor(
@Named("Genres") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,
new String[] {
BaseColumns._ID,
MediaStore.Audio.GenresColumns.NAME
}, null, null, null);
}
@Provides
Cursor providePlaylistCursor(@Named("Playlist") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
new String[] {
BaseColumns._ID,
MediaStore.Audio.PlaylistsColumns.NAME
}, null, null, null);
}
}
Available in
@CursorScope
@Subcomponent(modules = CursorModule.class)
public interface CursorComponent {
Cursor cursor();
}
I get this error
Error:(17, 11) Gradle: error: android.database.Cursor is bound multiple times:
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideSongCursor(@Named("Song") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideAlbumCursor(@Named("Album") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideArtistCursor(@Named("Artist") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.provideGenreCursor(@Named("Genres") com.merkmod.musician.application.Musician)
@Provides android.database.Cursor com.merkmod.musician.dependency.CursorModule.providePlaylistCursor(@Named("Playlist") com.merkmod.musician.application.Musician)
I
made multiple instances of Cursor and first annotated with @Named at the provider level, then it started giving me errors and couldn’t provide @Provides comments, so I used it in the constructor instead
Just like the code above. The problem is running a loop again and again, and I’m like stuck in the thing of completing the cursor, which we’d appreciate.
Solution
When you want to provide multiple variables of one type, you must use @Named
comments as follows:
Module
@CursorScope
public class CursorModule {
@Provides
@Named("songCursor")
Cursor provideSongCursor(
@Named("Song") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{
BaseColumns._ID,
MediaStore.Audio.AudioColumns.TITLE,
MediaStore.Audio.AudioColumns.ARTIST,
MediaStore.Audio.AudioColumns.ALBUM,
MediaStore.Audio.AudioColumns.DURATION
}, MediaStore.Audio.AudioColumns.IS_MUSIC + "=1", null, null);
}
@Provides
@Named("albumCursor")
Cursor provideAlbumCursor(
@Named("Album") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{
BaseColumns._ID,
MediaStore.Audio.AlbumColumns.ALBUM,
MediaStore.Audio.AlbumColumns.ARTIST,
MediaStore.Audio.AlbumColumns.NUMBER_OF_SONGS,
MediaStore.Audio.AlbumColumns.FIRST_YEAR
}, null, null, null);
}
@Provides
@Named("artistCursor")
Cursor provideArtistCursor(@Named("Artist") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
new String[] {
BaseColumns._ID,
MediaStore.Audio.ArtistColumns.ARTIST,
MediaStore.Audio.ArtistColumns.NUMBER_OF_ALBUMS,
MediaStore.Audio.ArtistColumns.NUMBER_OF_TRACKS
}, null, null,null);
}
@Provides
@Named("genreCursor")
Cursor provideGenreCursor(
@Named("Genres") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,
new String[] {
BaseColumns._ID,
MediaStore.Audio.GenresColumns.NAME
}, null, null, null);
}
@Provides
@Named("playListCursor")
Cursor providePlaylistCursor(@Named("Playlist") Musician musician) {
return musician.getApplicationContext().getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
new String[] {
BaseColumns._ID,
MediaStore.Audio.PlaylistsColumns.NAME
}, null, null, null);
}
}
Then when you want to inject, write the following:
@Inject
@Named("soundCursor")
Cursor soundCursor;
@Inject
@Named("albumCursor")
Cursor albumCursor;
@Inject
@Named("artistCursor")
Cursor artistCursor;
@Inject
@Named("genreCursor")
Cursor genreCursor;
@Inject
@Named("playListCursor")
Cursor playListCursor;
If you want to inject them in constructor injection, do the following:
@Inject
public SomeClassConstructor(@Named("album") Cursor cursur)
And what you wrote in the subcomponent interface I can’t understand what it is, it must be like this :
@CursorScope
@Subcomponent(modules = CursorModule.class)
public interface CursorComponent {
void inject(TheClassThatWantsToUseInject1 obj);
void inject(TheClassThatWantsToUseInject2 obj);
}
In your application component:
YourSubComponentInterface plus(CursorModule module);