How to use a ViewModelProvider.Factory when extends from AndroidViewModel
我想向我的ViewModel发送一个额外的参数,但这是从AndroidViewModel扩展过来的。
如何将此参数添加到ViewModelFactory类中?
ViewModel
1 2 3 4 | class ProjectViewModel(application: Application) : AndroidViewModel(application) { // need a param for project id... } |
ViewModelFactory
1 2 3 4 5 6 7 | class ProjectViewModelFactory(val projectId: Int): ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class< T >): T { // need to send this... return ProjectViewModel(projectId) as T } } |
注意:我注意到在文档中它说:AndroidViewModel子类必须具有一个接受Application作为唯一参数的构造函数。
所以我不知道是否可以(或者很好)去做我想做的事情。
获取ViewModel:
1 2 3 | viewModel = ViewModelProviders.of(this, new BListFactory(getActivity().getApplication(), 1)) .get(BListViewModel.class); |
工厂:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class BListFactory extends ViewModelProvider.NewInstanceFactory { @NonNull private final Application application; private final long id; public BListFactory(@NonNull Application application, long id) { this.application = application; this.id = id; } @NonNull @Override public <T extends ViewModel> T create(@NonNull Class< T > modelClass) { if (modelClass == BListViewModel.class) { return (T) new BListViewModel(application, id); } return null; } } |
AndroidViewModel:
1 2 3 4 5 6 7 8 9 | public class BListViewModel extends AndroidViewModel { private final long id; public BListViewModel(@NonNull Application application, final long id) { super(application); this.id = id; } } |
我引用了AndroidViewModelFactory类,并像这样使用它
1.AndroidViewModelFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class AndroidViewModelFactory private constructor( private val mApplication: Application, private val mName: String ) : ViewModelProvider.NewInstanceFactory() { override fun <T : ViewModel?> create(modelClass: Class< T >): T { return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) { try { modelClass.getConstructor( Application::class.java, String::class.java ).newInstance(mApplication, mName) } catch (e: Exception) { throw RuntimeException("Cannot create an instance of $modelClass", e) } } else super.create(modelClass) } companion object { private var sInstance: AndroidViewModelFactory? = null fun getInstance( application: Application, name: String ): AndroidViewModelFactory { if (sInstance == null) { sInstance = AndroidViewModelFactory(application, name) } return sInstance as AndroidViewModelFactory } } } |
2.ViewModelFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | object ViewModelFactory { fun <T : ViewModel?> createViewModel( activity: FragmentActivity, application: Application, name: String, cls: Class< T >? ): T { return ViewModelProvider( activity, AndroidViewModelFactory.getInstance(application, name) ).get(cls!!) } } |
3.NameViewModel
1 2 3 4 5 6 7 8 | class NameViewModel(application: Application, name: String) : AndroidViewModel(application) { val name = ObservableField<String>() init { this.name.set(name) } } |
4.NameActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class NameActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView(this, R.layout.activity_name) as ActivityNameBinding val viewModel = ViewModelFactory.createViewModel( this, application, "AndroidViewModel", NameViewModel::class.java ) binding.viewModel = viewModel } } |
5.activity_name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="viewModel" type="cn.eli.demo.viewmodel.NameViewModel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".viewmodel.NameActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="@{viewModel.name}"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout> |