How to manually clear a specific viewmodel?

时光怂恿深爱的人放手 提交于 2020-02-02 06:46:07

问题


As I understand when we call this code in fragments, we will have a viewmodel instance from activity ViewModelStore:

viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)

When fragments will end their lifecycle, the instance of this viewmodel will exist in ViewModelStore until the destruction of activity. ViewModelStore has a clear() method, but it clears all viewmodels in it. Is there some way to clear specific ViewModel?

Another solution is to scope ViewModel to parent fragment, but how do we initialize ViewModel in another fragment through ViewModelProviders.of()? Should I pass fragment or viewmodel instance to the next fragment?


回答1:


There is a hacky way to clear a specific ViewModel instance in which you should create your ViewModel instance with a customized key as stated below, and in order to clear it you should just create another instance (with different ViewModel class such as an EmptyViewModel class) but with the same key.

ShopFragment class:

class shopFragment : BaseFragment() {

    fun getViewModel() : ShopViewModel {
        return ViewModelProviders.of(activity!!).get(ShopViewModel.KEY, ShopViewModel::class.java)
    }

    fun clearViewModel() {
        ViewModelProviders.of(activity!!).get(ShopViewModel.KEY, EmptyViewModel::class.java) 
    }

    // Fragment logic ...

}

ShopViewModel class:

class ShopViewModel(application: Application) : AndroidViewModel(application) {

    companion object {
        const val KEY = "ShopViewModel"
    }

    // view model logic ...

}

EmptyViewModel which is a dummy ViewModel class:

class EmptyViewModel() : ViewModel() {
    // A dummy view model!
}

And the magic is happening inside ViewModelProvider class of androidx.lifecycle dependecy, the trick here is revealed when you take a look at the get() function of ViewModelProvider class which retrieves your previous ViewModel instance and compares it with the EmptyViewModel class and as they are not the same, it run mViewModelStore.put(key, viewModel);:

public class ViewModelProvider {
//...
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }

        viewModel = mFactory.create(modelClass);
        mViewModelStore.put(key, viewModel);
        //noinspection unchecked
        return (T) viewModel;
    }
// ...
}

As stated below inside ViewModelStore class of the androidx.lifecycle dependency, the put() method will retrieve the ShopViewModel and clear it, and replace EmptyViewModel instance.

public class ViewModelStore {
    //...
    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }
    //...
}


来源:https://stackoverflow.com/questions/55092532/how-to-manually-clear-a-specific-viewmodel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!