2

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)
    }
}
Itoun
  • 3,713
  • 5
  • 27
  • 47

0 Answers0