How to use a ViewModelProvider.Factory when extends from AndroidViewModel

后端 未结 2 820
庸人自扰
庸人自扰 2020-12-17 10:35

I want to send an extra parameter to my ViewModel, but this extends from AndroidViewModel. How can I add this parameter to the ViewModelFactory

相关标签:
2条回答
  • 2020-12-17 11:06

    Get ViewModel:

            viewModel = ViewModelProviders.of(this,
                    new BListFactory(getActivity().getApplication(), 1))
                    .get(BListViewModel.class);
    

    Factory:

    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:

    public class BListViewModel extends AndroidViewModel {
    
        private final long id;
    
        public BListViewModel(@NonNull Application application, final long id) {
            super(application);
            this.id = id;
        }
    }
    
    0 讨论(0)
  • 2020-12-17 11:15

    I referred to AndroidViewModelFactory class and use it like this

    1.AndroidViewModelFactory

    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

    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

    class NameViewModel(application: Application, name: String) : AndroidViewModel(application) {
    
        val name = ObservableField<String>()
    
        init {
            this.name.set(name)
        }
    }
    

    4.NameActivity

    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

    <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>
    
    0 讨论(0)
提交回复
热议问题