Было бы здорово, если бы вы опубликовали часть своего кода кинжала, чтобы увидеть, что происходит.Кажется, вы плохо вводите свой репозиторий.
С другой стороны, у вас есть некоторые проблемы с инициализацией ViewModel.Если вы отладите модель представления, вы увидите, что ваш LiveData
всегда равен нулю, потому что ваш FlightsRepository
не может быть введен.И вы пытаетесь наблюдать его в своем фрагменте, не проверяя его состояние -> NullPointerException.
Прежде всего, вы можете инициализировать переменную MutableLiveData
, несмотря на ваш репозиторий:
// View Model snippet
private MutableLiveData<Flights> flights;
private FlightsRepository flightsRepo;
@Inject
public OutboundFlightsViewModel(FlightsRepository flightsRepo) {
this.flightsRepo = flightsRepo;
}
public OutboundFlightsViewModel(){}
public void init() {
flights = new MutableLiveData<Flights>;
if (flightsRepo != null) {
flights.postValue(flightsRepo.getFlights());
}
}
public LiveData<Flights> getFlights() {
return this.flights;
}
В этом случае у вас есть пустые LiveData, которые можно наблюдать в вашем фрагменте, поэтому, когда вы исправляете инъекцию в хранилище и когда у нее есть значение для публикации, вы можете реагировать на эти изменения и делать все, что захотите.
Относительно классов Dagger:
Вам нужен ваш ApplicationComponent для привязки каждого модуля, который вы хотите предоставить:
@Singleton
@Component(modules = [(AndroidInjectionModule::class), (BuildersModule::class), (RepositoryModule::class)])
interface ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: AppController): Builder
fun build(): ApplicationComponent
}
fun inject(app: AppController)
}
Ваш класс BuildersModule обеспечивает каждую активность, которая будет внедрена.Если в вашей деятельности есть Фрагмент, который необходимо ввести, он также должен быть здесь.
@Module
abstract class BuildersModule {
@ContributesAndroidInjector(modules = [(YourViewModelModule::class)])
internal abstract fun contributeYourActivity(): YourActivity
}
В этом модуле вы объявляете каждый репозиторий, который хотите внедрить.
@Module
class RepositoryModule {
@Provides
fun yourRepository(): YourRepository {
return YourRepository()
}
}
Это ваш модуль модели представления, вам нужно создать фабрику модели представления и предоставить ее для внедрения.
@Module
class YourViewModelModule {
@Provides
fun providesYourViewModelFactory(yourRepository: YourRepository): YourViewModelFactory {
return YourViewModelFactory(yourRepository)
}
}
Вам понадобятся фабрики модели представления для введения параметров в классы модели представления.,
class YourViewModelFactory(private val repository: YourRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(YourViewModel::class.java)) {
return YourViewModel(repository) as T
}
throw IllegalArgumentException("unknown view model class")
}
}
Это ваша деятельность, которая содержит ваш фрагмент.Чтобы внедрить ваш фрагмент, вам нужно реализовать HasSupportFragmentInjection.
class OutboundActivity : AppCompatActivity, HasSupportFragmentInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return dispatchingAndroidInjector
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidInjection.inject(this)
}
}
Вот ваш фрагмент, теперь он может получать введенную вами фабрику моделей представлений.Обратите внимание, что теперь ваш ViewModelProvider принимает два параметра: this и viewModelFactory , чтобы ваша модель представления могла получать введенные параметры.
class OutboundFragment: Fragment {
@Inject
lateinit var viewModelFactory: YourViewModelFactory
private var viewModel: OutboundFlightsViewModel
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
AndroidSupportInjection.inject(this)
viewModel = ViewModelProviders.of(this, viewModelFactory).get(OutboundFlightsViewModel.class);
viewModel.init();
viewModel.getFlights().observe(this, flights -> {
// Update UI.
});
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_outbound, container, false);
}
}
И последнее, но не менее важное: вынеобходимо переопределить ваш метод onCreate в вашем классе приложения и инициализировать кинжал с его компонентами.Обратите внимание, что здесь вам нужно реализовать HasActivityInjection.
class AppController : Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun onCreate() {
super.onCreate()
// Registered a global instance of AppController
appControllerInstance = this
// Init Dagger
DaggerApplicationComponent.builder()
.application(this)
.build()
.inject(this)
}
override fun activityInjector(): AndroidInjector<Activity>? {
return dispatchingAndroidInjector
}
}
Извините, я писал это на Kotlin, как каждый день, и я забыл, что вы программировали на Java.Но не пугайтесь, это похоже, вы поймете без проблем.Дайте мне знать, если вы не можете понять что-нибудь.