Stack Overflow Asked by martinseal1987 on December 7, 2021
I’m new to dagger and hilt, I’m trying to use Hilt to get my adapter injected to my fragment using a builder (the fragment is actually in a fragment pager adapter so there’s multiple instance of it and the adapter), it seems set up correctly, I build the component before super in onCreate but the adapter is null when trying to access it later in the fragment, I wonder if maybe I need to provide it somehow later on so for instance I have my adapter in my fragment
@AndroidEntryPoint
public class CardHolderFragment extends Fragment {
public CardAdapter cardAdapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
DaggerCardAdapterComponent.builder()
.cardAdapterDependencies(() -> layoutIdentifier)
.build().inject(this);
super.onCreate(savedInstanceState);
cardAdapter.notifyDataSetChanged(); // CardAdapter.notifyDataSetChanged()' on a null object reference
so my question is if the component is setup correctly should this work or am I missing a step?
What I feel like doing is something like cardAdapter = DaggerCardAdapterComponent.getCardAdapter but I can’t put a provides methods in a component, I had a look through the dagger migration guide here which is a little complicated for me as I only had a few weeks with dagger before switching to hilt, but the guide mentions
Finally, you may have to redesign some things if they were configured differently for different activity or fragment components. For example, you could use a new interface on the activity to provide the object.
so I tried this which makes me implement the interface and then return a card adapter but I wasn’t sure what I should be returning here, any help welcome
heres my card adapter component
@Component(dependencies = CardAdapterDependencies.class, modules = {TypeFactoryModule.class,
ItemTouchListenerModule.class, GlideModule.class})
public interface CardAdapterComponent {
void inject(CardHolderFragment cardHolderFragment);
@Component.Builder
interface Builder {
Builder cardAdapterDependencies(CardAdapterDependencies cardAdapterDependencies);
CardAdapterComponent build();
}
interface HasCardAdapter{
CardAdapter getCardAdapter();
}
}
and heres my card adapter constructor
@Inject
public CardAdapter(
ItemTouchListener onItemTouchListener,
String layoutIdentifier,
TypeFactory typeFactory,
RequestManager glide
) {
this.onItemTouchListener = onItemTouchListener;
this.typeFactory = typeFactory;
this.layoutIdentifier = layoutIdentifier;
this.glide = glide;
this.elements = new ArrayList<>();
}
First of all you don't need to use @AndroidEntryPoint
if you are building your dependent component, even in my case at dynamic feature modules using @AndroidEntryPoint
caused it not to compile.
Edit: In your situation building a dependent component or building component with builder does not look necessary. If so, you can use the answer below will help, if you don't need dependent component I will add another edit to do it simple way.
You should use EntryPointAccessors.fromApplication()
, EntryPointAccessors.fromActivity()
or EntryPointAccessors.fromFragment()
to create an interface that has provision methods with @InstallIn
and @EntryPoint
annotations. I explained here how to build with dependent components and dynamic feature modules using Hilt and you can find the full sample in this git repo.
First create a module with dependencies you provide:
@Module
@InstallIn(ApplicationComponent::class)
class CoreModule {
@Singleton
@Provides
fun provideCoreDependency(application: Application) = CoreDependency(application)
@Provides
fun provideCoreActivityDependency(context: Application) = CoreActivityDependency(context)
}
You can change ApplicationComponent
to ActivityComponent
or FragmentComponent
depending on your structure.
Then build a dependencies interface with @EntryPoint
and @InstallIn
annotations and provision methods which is how you provide the dependencies to dependent components.
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface CoreDependencies {
/*
* Provision methods to provide dependencies to components that
* depend on this component
*/
fun coreDependency(): CoreDependency
fun coreActivityDependency(): CoreActivityDependency
}
Now build the component you should create, it's CardAdapterComponent
for you
@Component(
dependencies = [CoreDependencies::class],
modules = [CameraModule::class]
)
interface CameraComponent {
fun inject(cameraFragment1: CameraFragment1)
fun inject(cameraFragment2: CameraFragment2)
fun inject(cameraActivity: CameraActivity)
@Component.Factory
interface Factory {
fun create(coreDependencies: CoreDependencies, @BindsInstance application: Application): CameraComponent
}
}
I used factory pattern, you can use builder if you wish, both the same.
To inject your dependent component to Activity
you need to get component using EntryPoints
.
private fun initHiltDependencyInjection() {
val coreComponentDependencies = EntryPointAccessors.fromApplication(
applicationContext,
CoreDependencies::class.java
)
DaggerCameraComponent.factory().create(
coreComponentDependencies,
application
)
.inject(this)
}
To inject to the Fragment
:
private fun initCoreDependentInjection() {
val coreComponentDependencies = EntryPointAccessors.fromApplication(
requireActivity().applicationContext,
CoreDependencies::class.java
)
DaggerCameraComponent.factory().create(
coreComponentDependencies,
requireActivity().application
)
.inject(this)
}
Answered by Thracian on December 7, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP