【问题标题】:Instantiating Viewmodel with Activity in constructor with Navigation Component使用导航组件在构造函数中使用 Activity 实例化 Viewmodel
【发布时间】:2020-06-20 08:29:52
【问题描述】:

全部。 我有一个视图模型,我想在所有片段和它们所在的活动之间共享。问题是,视图模型需要引用活动以构建附加到它的数据库。我正在使用 Dagger2 注入依赖项,而不是实例化它们。

我能做些什么来解决这个问题? 我尝试使用参考添加捆绑包,但没有用。我尝试使用导航控制器启动第一个片段,但这也不起作用,因为我无法在参数中传递活动引用。 我无法通过共享视图模型传递引用,因为没有引用我无法实例化它。所以我完全迷路了。

class HooskBankBranchesFragment(private val activity: AccountDetailsActivity) : androidx.fragment.app.Fragment() {

    @Inject
    lateinit var viewModel: AccountsProfileViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {



        return inflater.inflate(R.layout.hoosk_bank_branches_fragment, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        DaggerAccountsProfileComponent.builder()
            .accountsProfileModule(AccountsProfileModule(activity))
            .appComponent((activity?.application as HooskApp).component())
            .build().inject(this)


        rv_bankAccounts.layoutManager = LinearLayoutManager(activity)

        viewModel.state.observe(viewLifecycleOwner){
            when(it){
                is AccountsProfileViewModelState.OnDatabaseAccountsFetched -> rv_bankAccounts.adapter = BankDetailsRvAdapter(it.bankAccounts)
                is AccountsProfileViewModelState.Error -> Toast.makeText(activity, it.throwable.message, Toast.LENGTH_LONG).show()
            }
        }

        viewModel.getAccounts()


    }
}

这是无法创建的 Fragment 类,因为我无法使用 NavController 传递活动的引用。

class AccountsProfileViewModel(private val repository: AccountProfileRepository) : ViewModel() {


    private val _state = MutableLiveData<AccountsProfileViewModelState>()

    val state: LiveData<AccountsProfileViewModelState>
        get() = _state

    fun getAccounts() {
        viewModelScope.launch {
            try {
                _state.value = AccountsProfileViewModelState.OnDatabaseAccountsFetched(repository.getAccounts())
            } catch (error: Throwable) {
                _state.value = AccountsProfileViewModelState.Error(error)
            }
        }
    }

    fun getOnlineAccounts(accessCode: String) {
        viewModelScope.launch {
            try {
                _state.value = AccountsProfileViewModelState.OnOnlineAccountFetched(repository.getOnlineAccounts("Bearer $accessCode"))
            } catch (error: Throwable) {
                _state.value = AccountsProfileViewModelState.Error(error)
            }
        }
    }

    fun addAccount(account: BankAccountAPIModel) {
        viewModelScope.launch {
            try {
                repository.addAccount(account)
            } catch (error: Throwable) {
                _state.value = AccountsProfileViewModelState.Error(error)
            }
        }
    }

    fun getAccount(url: String){
        val sanitizer = UrlQuerySanitizer(url)
        viewModelScope.launch {
            try {
                val accessToken = repository.getAccessCode(sanitizer.getValue("code"))
                val onlineAccount = repository.getOnlineAccounts("Bearer " + accessToken.accessToken)
                _state.value = AccountsProfileViewModelState.OnOnlineAccountFetched(onlineAccount)

                repository.addAccount(onlineAccount)
                _state.value = AccountsProfileViewModelState.OnDatabaseAccountsFetched(repository.getAccounts())

            }catch (error: Throwable){
                _state.value = AccountsProfileViewModelState.Error(error)
            }
        }
    }

    fun getAccessCode(url: String) {
        val sanitizer = UrlQuerySanitizer(url)
        viewModelScope.launch {
            try {
                _state.value = AccountsProfileViewModelState.OnAccessTokenRetrieved(repository.getAccessCode(sanitizer.getValue("code")))
            } catch (error: Throwable) {
                _state.value = AccountsProfileViewModelState.Error(error)
            }
        }
    }


}



sealed class AccountsProfileViewModelState{
    object Loading : AccountsProfileViewModelState()
    data class Error(val throwable: Throwable): AccountsProfileViewModelState()
    data class OnAccessTokenRetrieved(val accessToken: AccessToken): AccountsProfileViewModelState()
    data class OnOnlineAccountFetched(val bankAccount: BankAccountAPIModel): AccountsProfileViewModelState()
    data class OnDatabaseAccountsFetched(val bankAccounts: List<BankAccountAPIModel>): AccountsProfileViewModelState()
}

这是我的 ViewModel,我不确定这是否有帮助。

我确实设法做的,我很快意识到这是不正确的,我创建了两次视图模型,一次附加到活动,一次附加到片段。仅在我重新启动应用程序后才更新数据库中的片段。我意识到那是错误的,因为我无法观察到确切的视图模型。

【问题讨论】:

    标签: android android-fragments kotlin dependency-injection viewmodel


    【解决方案1】:

    我发现了我的问题。

            DaggerAccountsProfileComponent.builder()
                .accountsProfileModule(AccountsProfileModule(activity))
                .appComponent((activity?.application as HooskApp).component())
                .build().inject(this)
    

    我删除了构造函数中的引用并将 AccountsProfileModule(activity) 更改为:

            DaggerAccountsProfileComponent.builder()
                .accountsProfileModule(AccountsProfileModule(activity as AccountDetailsActivity))
                .appComponent((activity?.application as HooskApp).component())
                .build().inject(this)
    ```
    

    【讨论】:

      猜你喜欢
      • 2020-07-18
      • 2021-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2023-03-04
      相关资源
      最近更新 更多