微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么Android中需要viewmodel工厂?

我们一直在讨论这个问题,但是我们不知道创建视图模型工厂来创建视图模型而不是直接实例化视图模型的原因.创建仅创建视图模型的工厂有什么好处?

我只是举了一个简单的示例,说明我没有工厂如何做到这一点

这是kodein模块:

val heroesRepositoryModel = Kodein {
    bind<HeroesRepository>() with singleton {
        HeroesRepository()
    }

    bind<ApiDataSource>() with singleton {
        DataModule.create()
    }

    bind<Mainviewmodel>() with provider {
        Mainviewmodel()
    }
}

我不使用工厂实例化viewmodel的Activity部分

class MainActivity : AppCompatActivity() {
    private lateinit var heroesAdapter: HeroAdapter
    private lateinit var viewmodel: Mainviewmodel
    private val heroesList = mutablelistof<Heroes.MapHero>()
    private var page = 0
    private var progressBarUpdated = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewmodel = viewmodelProviders.of(this)
                .get(Mainviewmodel::class.java)
        initAdapter()
        initObserver()
        findHeroes()
    }

我直接实例化用例的viewmodel,而无需在构造函数中使用它

class Mainviewmodel : viewmodel(), Coroutinescope {

    private val heroesRepository: HeroesRepository = heroesRepositoryModel.instance()
    val data = mutablelivedata<List<Heroes.MapHero>>()

    private var job: Job = Job()
    override val coroutineContext: CoroutineContext
        get() = uiContext + job

    fun getHeroesFromrepository(page: Int) {
        launch {
            try {
                val response = heroesRepository.getHeroes(page).await()
                data.value = response.data.results.map { it.convertToMapHero() }
            } catch (e: HttpException) {
                data.value = null
            } catch (e: Throwable) {
                data.value = null
            }
        }
    }

    override fun onCleared() {
        super.onCleared()
        job.cancel()
    }
}

所以这里有一个使用工厂的例子

class ListFragment : Fragment(), KodeinAware, ContactsAdapter.OnContactListener {

    override val kodein by closestKodein()

    private lateinit var adapterContacts: ContactsAdapter

    private val mainviewmodelFactory: MainviewmodelFactory by instance()
    private val mainviewmodel: Mainviewmodel by lazy {
        activity?.run {
            viewmodelProviders.of(this, mainviewmodelFactory)
                .get(Mainviewmodel::class.java)
        } ?: throw Exception("Invalid Activity")
    }

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_list, container, false)
    }

viewmodelfactory:

class MainviewmodelFactory (private val getContacts: GetContacts) : viewmodelProvider.Factory {

    override fun <T : viewmodel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(Mainviewmodel::class.java)) {
            return Mainviewmodel(getContacts) as T
        }
        throw IllegalArgumentException("UnkNown viewmodel class")
    }
}

和视图模型:

class Mainviewmodel(private val getContacts: GetContacts) : Baseviewmodel() {
    lateinit var gamesList: LiveData<PagedList<Contact>>
    var contactsSelectedData: mutablelivedata<List<Contact>> = mutablelivedata()
    var contactsSelected: ArrayList<Contact> = ArrayList()
    private val pagedListConfig by lazy {
        PagedList.Config.Builder()
                .setEnablePlaceholders(false)
                .setinitialLoadSizeHint(PAGES_CONTACTS_SIZE)
                .setPageSize(PAGES_CONTACTS_SIZE)
                .setPrefetchdistance(PAGES_CONTACTS_SIZE*2)
                .build()
    }

这是完整的第一个示例:

https://github.com/ibanarriolaIT/Marvel/tree/mvvm

以及完整的第二个示例:

https://github.com/AdrianMeizoso/Payment-App

解决方法:

我们不能自行创建viewmodel.我们需要Android提供的viewmodelProviders实用程序来创建viewmodels.

但是viewmodelProviders只能实例化没有arg构造函数viewmodels.

因此,如果我有一个带有多个参数的viewmodel,则需要使用一个Factory,可以将其传递给viewmodelProviders,以便在需要Myviewmodel实例时使用.

例如 –

public class Myviewmodel extends viewmodel {
    private final MyRepo myrepo;
    public Myviewmodel(MyRepo myrepo) {
         this.myrepo = myrepo;
    }
}

要实例化此viewmodel,我需要有一个工厂,viewmodelProviders可以使用该工厂来创建其实例.

viewmodelProviders实用程序无法使用参数构造函数创建viewmodel的实例,因为它不知道如何以及在构造函数中传递哪些对象.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐