I am using PageKeyedDataSource to make paging by calling an API and using Retrofit.
And I am using Dagger 2 to make the dependency injection.
@Provides
Repository provideRepository(...) {
...
}
@Provides
PageKeyedVideosDataSource providePageKeyeVideosDataSource(Repository repository) {
...
}
@Provides
VideoDataSourceFactory provideVideoDataSourceFactory(PageKeyedHomeVideosDataSource pageKeyedHomeVideosDataSource) {
...
}
@Provides
ViewModelFactory provideViewModelFactory(Repository repository, VideoDataSourceFactory videoDataSourceFactory) {
...
}
Now, I need to do the same thing, however my call needs a new parameter: an id.
@GET(Urls.VIDEOS_BY_CATEGORY)
Observable<RequestVideo> getVideosByCategory(
@Path("id") int categoryId, // <-- Now I need this new parameter
@Query("per-page") int perPage,
@Query("page") int page);
Before, my PageKeyedVideosDataSource needed only the page and the per-page to make the call, it was easy. However, now I need to put this new parameter id dynamically inside the PageKeyedDataSource.
I saw PagingWithNetworkSample and figured it out that they put a new parameter in PagedKeyedDataSource by adding it in the constructor. Then, I thought about doing this:
public PageKeyedCategoryVideosDataSource(int categoryId, Repository repository) {
this.categoryId = categoryId;
this.repository = repository;
}
However, if I add the id in the constructor, I think I'll not be able to use dagger 2 anymore because by using dagger 2 the PageKeyedVideosDataSource is not created dynamically, therefore, I can't keep changing the value of the id.
I need to create the PageKeyedDataSource dynamically like this:
int categoryId = getCategoryId();
PageKeyedVideosDataSource dataSource = new PageKeyedVideosDataSource(categoryId, repository);
Although late answer, maybe could help others.
When you need "dynamic" parameter to be passed into dagger's graph, dagger can't create instance of your dependency. In that case dagger would provide Factory for your PageKeyedVideosDataSource, but you'd have to manually pass parameters into constructor.
You would have factory (kotlin example, but would work in java as well):
class PageKeyedVideosDataSourceFactory @Inject constructor(
private val repository: Repository
) {
fun create(categoryId: Int): PageKeyedVideosDataSource {
return PageKeyedVideosDataSource(categoryId, repository)
}
}
and then instead of injecting the instance, you'd inject the PageKeyedVideosDataSourceFactory
factory and manually call factory.create(categoryId)
on it.
If you'd want to automate the factory creation, you may check AssistedInject library (from Square) which can create implementation of the factory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With