目录
我在Google Playstore上的应用程序
github代码
简介
- 本系列将是我面临的问题以及如何解决问题的非正式演示。本系列中的每个博客文章都将是独特的,并且与其他博客文章是独一无二的,因此请随时环顾四周。
ViewModels和Google的计费库的问题
- 阅读Google Play billing library,我遇到了这一部分:
It's strongly recommended that you have one active BillingClient connection open at one time to avoid multiple PurchasesUpdatedListener callbacks for a single event.
-
大声读出来似乎是合乎逻辑的,没有什么可担心的。但是,这使我问这个问题,
When is my code creating a BillingClient and how is it even possible create multiple of them?
-
事实证明,我拥有Billingclient HERE,并将其创建实例委派给ViewModel HERE。因此,这意味着每次我创建某个ViewModel时,都会创建一个BillingClient,并且将创建publiceUpdateDlistener回调。然后,这将我们提出了
When does our ViewModel get created?
的问题。要回答这个问题,我们必须了解一些有关ViewModel范围的信息。
ViewModel Scopes
- 每当创建一个ViewModel时,都会将其范围示为实现
ViewModelStoreOwner
接口的对象。这可以是一个活动,碎片,导航图或实现ViewModelStoreOwner接口的任何其他类。考虑到这一点很重要,因为ViewModel的生命周期直接与其范围相关。这意味着ViewModel保留在存储器中,直到它范围范围的ViewModelStoreOwner消失为止。这可能是由于以下原因而发生的:
1)当活动完成(用户解雇)
2)当碎片从碎片曼格脱离时
3)在导航期间,当它从后堆中删除时
范围API
- 为了确定我们的视图模型,我们将重点关注这两个扩展功能:
1)viewModels():此扩展功能将把视图模型范围范围为最接近的ViewModelsStoreOwner。如果它在片段内使用(这是我使用的),则将范围范围范围内。如果在活动内部使用,则将范围为活动。
2)ActivityViewModels():通过使用此扩展功能,我们能够从片段的内部获得活动示波的ViewModel。因此,对于片段的oncreateview()方法,我们可以做到这一点:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val billingViewModel: BillingViewModel by activityViewModels()
- 这将使我们的
billingViewModel
能够像活动一样持续。当您在多个片段中使用val billingViewModel: BillingViewModel by activityViewModels()
时,这会变得非常有趣。您认为会发生什么?另一个活动范围的视图模型是否得到创建,或者Android系统恢复同一实例????正确的! Android系统恢复同一实例。
多个billingclient连接问题
- 现在,我们俩都知道一些范围,我们可以谈论
multiple BillingClient connection problem
,以及为什么将范围范围范围的范围和导航组件组合起来会导致它。在我的应用中,我使用Navigation Component,该Navigation Component处理所有片段实例化本身,这真的很棒。当我们将ViewModel示意为片段时,然后我们的用户围绕应用程序导航时,就会出现multiple BillingClient connection problem
,而不会从后堆栈中弹出片段。高水平的有问题的导航看起来像这样:
-
箭头每次从房屋片段导航到订阅片段时都会演示。
-
现在,由于视图模型范围为订阅片段。每次用户导航到该片段时,导航组件都会创建订阅片段的新实例,该实例创建了BillingViewModel的新实例,该实例创建了一个新的BillingClient实例,创建一个publicesUpdateDlistener回调,并且每个实例都在存储这些实例在后堆上。这会导致单个事件有多个
PurchasesUpdatedListener
回调(真正的麻烦)。
解决多个Billingclient连接问题
- 解决此问题的解决方案非常容易,我们只需要使用
activityViewModels()
扩展功能将ViewModel的范围从片段更改为活动。因此,在片段的onCreateView()
中,我们可以做到这一点:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val billingViewModel: BillingViewModel by activityViewModels()
- 现在可以将
billingViewModel
传递给我们的组合:
binding.composeView.apply{
setContent {
// composable function
MainView(
billingViewModel = billingViewModel
)
}
}
- 正如我之前提到的,
activityViewModels()
非常有趣,因为它只会创建一个billingViewModel
的实例,然后如果我们从任何其他片段中调用val billingViewModel: BillingViewModel by activityViewModels()
系统将重复使用同一实例。因此,随着片段通过导航组件自动创建和破坏,只有在用户完全驳回活动并被销毁的活动后,billingViewModel
才会被销毁。
结论
- 感谢您抽出宝贵的时间阅读我的博客文章。如果您有任何疑问或疑虑,请在下面发表评论或在Twitter上与我联系。