So basically, everything is in the title. I use Dagger2
, ViewModelFactory
and ViewModelProvider
but it always create a new instance of my ViewModel
on each screen rotation. I saw that I got the same Factory at each screen rotation but the viewModel
got from the ViewModelProvider
is always a new one.
I saw this answer but as you can see I'm already using this way to instantiate my VM.
The repo ready to build is available here
ViewModelFactoryModule:
@Module
class ViewModelFactoryModule {
@Singleton
@Provides
fun provideContactListViewModelFactory(repository: Repository) = ContactListViewModel.ContactListViewModelFactory(repository)
}
Instantiation of ViewModel:
class ContactListFragment : BaseFragment() {
private lateinit var adapter: ContactListAdapter
private lateinit var contactDetailDialog:ContactDetailDialog
private lateinit var dataStorage: DataStorage
@Inject
lateinit var viewModelFactory: ContactListViewModel.ContactListViewModelFactory
private lateinit var viewModel: ContactListViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_contact_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this, viewModelFactory).get(ContactListViewModel::class.java)
dataStorage = DataStorage(requireContext())
initView()
initListeners()
}
}
ViewModel & Factory:
class ContactListViewModel @Inject constructor(private val repository: Repository) :
ViewModel() {
val contactsLiveData: MutableLiveData<ContactResult> = MutableLiveData()
val loadingState: MutableLiveData<LoadingState> = MutableLiveData()
}
@Singleton
class ContactListViewModelFactory @Inject constructor(private val repository: Repository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ContactListViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return ContactListViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Component class:
@Singleton
@Component(
modules =
[AndroidSupportInjectionModule::class,
NetworkModule::class,
ViewModelFactoryModule::class,
RoomModule::class,
ActivityBuilder::class]
)
interface ContactAppComponent : AndroidInjector<ContactApp> {
fun inject(contactViewHolder: ContactListAdapter.ContactViewHolder)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ContactAppComponent
}
}
App Class:
class ContactApp: Application(), HasAndroidInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun onCreate() {
super.onCreate()
Timber.plant(Timber.DebugTree())
contactAppComponent = DaggerContactAppComponent.builder()
.application(this)
.build()
contactAppComponent.inject(this)
}
override fun androidInjector(): AndroidInjector<Any> {
return dispatchingAndroidInjector
}
companion object {
lateinit var contactAppComponent: ContactAppComponent
}
}
BaseFragment:
open class BaseFragment : Fragment() {
override fun onAttach(context: Context) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}
}