标签: android-viewmodel

Android:ViewModel.无法调用观察者方法

我正在使用新的拱门.来自谷歌的组件.

我有活动登录/注册管理片段,感谢 FragmentTransaction

Activity->RegisterFragment (with ViewPager) -> RegistrationSteps (adapter)

在RegisterFragment里面我有ViewPager.我希望里面的所有页面ViewPager都使用相同的ViewModel.

这些都是注册步骤(RegistrationStepFragment),其采用母公司RegistrationFragment LifecycleOwner该范围的视图模型到它-我只是想视图模型先限定这个父片段.

RegistrationFragment.class来自

public interface FragmentViewPagerListener<T extends LifecycleFragment> {
    void nextPage();
    T getLifecycleFragment();
}
Run Code Online (Sandbox Code Playgroud)

RegistartionSteps(页面)来自

public abstract class RegisterStepFragment extends LifecycleFragment {
    protected FragmentViewPagerListener mListener;
    protected RegisterViewModel mViewModel;

    public void setListener(FragmentViewPagerListener fragmentViewPagerListener) {
        this.mListener = fragmentViewPagerListener;
    }

    protected abstract void observeViewModel();

    @Override
    public void onCreated(@Nullable Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);
        mViewModel = ViewModelProviders.of(mListener.getLifecycleFragment()).get(RegisterViewModel.class);
        observeViewModel();
    }

    protected abstract boolean validateData();
}
Run Code Online (Sandbox Code Playgroud)

一切顺利,直到我达到3页,我想向后移动(到第二页)然后抛出异常mViewPager.setCurrentItem(1) …

android android-lifecycle android-fragments android-viewmodel

10
推荐指数
0
解决办法
5107
查看次数

清除共享视图模型

我正在使用 Koin 将 viewModel 注入片段。我的应用程序是单一活动。我只需要在 servisFragment 和 partFragment 中使用 sharedViewModel。我想在用红色标记的导航后从 Activity 中清除该 viewModel。

我怎样才能做到这一点?

导航

注入viewModel的代码

    private val servisViewModel by sharedViewModel<ServisViewModel>()
Run Code Online (Sandbox Code Playgroud)

Koin 共享视图模型

inline fun <reified T : ViewModel> Fragment.sharedViewModel(
    name: String? = null,
    noinline from: ViewModelStoreOwnerDefinition = { activity as 
    ViewModelStoreOwner },
    noinline parameters: ParametersDefinition? = null
) = lazy { getSharedViewModel<T>(name, from, parameters) }
Run Code Online (Sandbox Code Playgroud)

感谢您的任何帮助。

android kotlin android-viewmodel koin android-jetpack

10
推荐指数
1
解决办法
1671
查看次数

ViewPager2/Tabs 的 ViewModel 状态问题

我遵循 MVVM 模式 - 这意味着我为每个 Fragment 都有一个 ViewModel。

我使用 ViewPager2添加了两个选项卡。

我的适配器看起来像这样:

@Override
public Fragment createFragment(int position) {
    switch (position) {
        case 0:
            return new MergedItemsFragment();
        case 1:     
            return new ValidatedMergedItemsFragment();
    }
    return new MergedItemsFragment();
}
Run Code Online (Sandbox Code Playgroud)

选项卡正在工作。但是,我注意到我的 MergedItemsFragment 的 ViewModel 表现得很奇怪。在我添加标签之前,我像这样导航到 Fragment:

NavHostFragment.findNavController(this).navigate(R.id.action_roomFragment_to_itemsFragment);
Run Code Online (Sandbox Code Playgroud)

当我离开那个片段NavHostFragment.findNavController(this).popBackStack()然后返回到那个片段时,我会得到一个新的空 ViewModel。这是有意的。

使用新方法,我正在使用return new MergedItemsFragment(). 当我离开那个片段并稍后返回时,我得到一个包含旧数据的 ViewModel 。这是一个问题,因为旧数据不再相关,因为用户在另一个片段中选择了不同的数据。


更新 #1

我意识到他实际上将所有片段保存在内存中,因为多次调用相同的打印语句。它被调用的次数随着我离开并返回该屏幕的次数而增加。因此,如果我离开并返回 10 次并旋转我的设备,他实际上会执行一行 10 次。任何猜测如何以与 ViewModels 一起工作的方式使用导航组件实现 Tabs/ViewPagers?


更新 #2

我这样设置我的 ViewModel:

@Override
public …
Run Code Online (Sandbox Code Playgroud)

java android android-viewmodel android-architecture-navigation android-viewpager2

10
推荐指数
1
解决办法
1955
查看次数

什么 ViewModelStoreOwner 用于 Fragment 中的 ViewModelProvider?

我创建了一个测试活动来更新我的 MyViewModel 中的一些文本。

我想在Fragment 中观察这些变化,但是当我使用

MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
Run Code Online (Sandbox Code Playgroud)

它给了我一个与活动中使用的不同的 MyViewModel 实例,这导致我onChanged()在片段中的回调不被调用。

只有当我将相同的片段代码修改为

HomeViewModel homeViewModel = new ViewModelProvider(getActivity()).get(HomeViewModel.class);
Run Code Online (Sandbox Code Playgroud)

片段是否获得与活动相同的 MyViewModel 实例 - 所以 onChanged()被成功调用。

但是,我不确定使用getActivity()作为 ViewModelStoreOwner 是否是正确的做事方式,因为我没有在任何地方的任何示例中看到过这种情况。我想知道在这种情况下是否应该使用更好的 ViewModelStoreOwner?

android android-fragments android-livedata android-viewmodel

10
推荐指数
2
解决办法
4513
查看次数

如何在 Android MVVM 虚拟机中模拟父子关系?

我正在开发一个 Android 钢琴“测验”应用程序 - 用户点击钢琴键,然后单击黄色的“检查”按钮提交答案进行评估,并查看在钢琴上绘制的正确答案。主要QuizActivity有这样的布局: 在此处输入图片说明

屏幕的上部包含几个控件(文本、提交按钮等)。屏幕的下部由一个自定义PianoView组件占据,用于处理钢琴键盘的绘制。

根据MVVM原则,PianoView应该有自己的PianoViewModel,将其状态(即当前按下的键,突出显示的键等)存储在KeysStateRepository. 封闭的QuizActivity也应该有一个QuizActivityViewModel, 来处理各种控制(提交答案,跳过问题......)。将QuizActivityViewModel需要能够从查询中选择键PianoView(或者更确切地说,从它的KeysStateRepository),他们提交领域层进行评估,然后将结果发回PianoView的可视化。

换言之,所述QuizActivityViewModel应该拥有/是的母体PianoViewViewModel以促进通信和数据共享。

如何建模这种父子关系以在 ViewModel 之间进行通信?

AFAIK aViewModel不能依赖于另一个ViewModel(我会通过什么ViewModelStoreOwner来获得ViewModel另一个中的 a Viewmodel?)。我认为至少用Dagger-Hilt是不可能实现的。

想到了解决此问题的三种解决方案,但都无法使用:

1 - 视图之间共享数据的官方方式

Android 开发文档建议使用shared ViewModel来促进两个 Fragment / Views 之间的数据共享。但是,这不适合我的用例。的PianoView(或它的视图模型)应该是其状态的具有唯一所有者Repository …

java android mvvm android-viewmodel dagger-hilt

10
推荐指数
1
解决办法
652
查看次数

ViewModel中的SavedStateHandle和currentBackStackEntry是否相同?

我想使用 saveStateHandle 将一些数据从活动直接传递到片段的视图模型。

在我的活动中我有:

navController.addOnDestinationChangedListener { controller, _, _ ->
    controller.currentBackStackEntry?.savedStateHandle?.set(
        "foo",
         "bar"
    )
}
Run Code Online (Sandbox Code Playgroud)

所以viewModel中的代码如下所示:

MyViewModel(state: SavedStateHandle) : ViewModel() {

    init {
        state
            ?.getStateFlow("foo", "")
            ?.onEach { /* do something */ }
            ?.launchIn(viewModelScope)
    }

Run Code Online (Sandbox Code Playgroud)

由于某种原因,期望值bar永远不会被发出。

我已经检查了Fragment本身,数据就在那里:

val handle = findNavController().currentBackStackEntry?.savedStateHandle

handle?.getLiveData<String>("foo")?.observe(viewLifecycleOwner) {
    // here it is

}
Run Code Online (Sandbox Code Playgroud)

但是是否有可能将数据直接传递到 viewModel 的 savingStateHandle ?我相信应该是这样,因为导航器以某种方式通过了。

android android-savedstate android-viewmodel android-jetpack-navigation viewmodel-savedstate

10
推荐指数
0
解决办法
558
查看次数

CompoundView(自定义视图)中的 ViewModel 引用

我正在遵循MVVM使用Android Architecture ComponentsData Binding库的架构。

TL; 博士

ViewModel在复合视图中引用对象是否违反了 MVVM 架构?我查看了 Google 的示例,只看到它在 Activity/Fragment XML 中使用,但没有在自定义视图中使用。

有问题的代码

我有一个复合视图,我想在许多地方重复使用它。它从 XML 实例化。该视图根据用户输入进行填充。我想确保用户输入的任何内容都能在方向更改中幸存下来。请考虑我匆忙编写的以下代码来说明场景:

public class RestaurantActivity extends AppCompatActivity {

    RestaurantViewModel viewModel;

    RestaurantActivityBinding binding;

    @Override
    public void onCreate( Bundle savedInstanceState ) {
        super.onCreate( savedInstanceState );

        binding = DataBindingUtil.setContentView(this, R.layout.restaurant_activity );

        viewModel = ViewModelProviders.of( this ).get( RestaurantViewModel.class );

        //is this "legal" for MVVM
        binding.selectionView.setRestaurantViewModel( viewModel );

        viewModel.extraHotSause.observe ( this, new Observer() {

          @Override
          void onChange(Boolean extraHotSauce ) {
               binding.selectionView.extraHotSauce( extraHotSauce …
Run Code Online (Sandbox Code Playgroud)

android mvvm android-viewmodel android-architecture-components

9
推荐指数
0
解决办法
3027
查看次数

如何使用ViewModel和Databinding实现验证?

使用ViewModel和Databinding验证表单数据的最佳方法是什么?

我有一个简单的Sign-Up活动,该活动链接绑定布局和ViewModel

class StartActivity : AppCompatActivity() {

    private lateinit var binding: StartActivityBinding
    private lateinit var viewModel: SignUpViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = ViewModelProviders.of(this, SignUpViewModelFactory(AuthFirebase()))
                .get(SignUpViewModel::class.java);

        binding = DataBindingUtil.setContentView(this, R.layout.start_activity)
        binding.viewModel = viewModel;

        signUpButton.setOnClickListener {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ViewModel4 ObservableFieldssignUp()在向服务器提交数据之前应该验证数据的方法。

class SignUpViewModel(val auth: Auth) : ViewModel() {
    val name: MutableLiveData<String> = MutableLiveData()
    val email: MutableLiveData<String> = MutableLiveData()
    val password: MutableLiveData<String> = MutableLiveData()
    val passwordConfirm: MutableLiveData<String> = MutableLiveData()

    fun signUp() {

        auth.createUser(email.value!!, password.value!!)
    }
} …
Run Code Online (Sandbox Code Playgroud)

validation android kotlin android-databinding android-viewmodel

9
推荐指数
2
解决办法
5706
查看次数

如何确保在 Android 单元测试中调用 ViewModel#onCleared?

这是我的 MWE 测试类,它依赖于 AndroidX、JUnit 4 和 MockK 1.9:

class ViewModelOnClearedTest {
    @Test
    fun `MyViewModel#onCleared calls Object#function`() = mockkObject(Object) {
        MyViewModel::class.members
            .single { it.name == "onCleared" }
            .apply { isAccessible = true }
            .call(MyViewModel())

        verify { Object.function() }
    }
}

class MyViewModel : ViewModel() {
    override fun onCleared() = Object.function()
}

object Object {
    fun function() {}
}
Run Code Online (Sandbox Code Playgroud)

注意:该方法在超类中受保护ViewModel

我想验证MyViewModel#onCleared调用Object#function. 上面的代码通过反射实现了这一点。我的问题是:我可以以某种方式运行或模拟 Android 系统以便onCleared调用该方法,这样我就不需要反射吗?

来自onClearedJavaDoc:

当这个 ViewModel 不再使用时会调用这个方法,并且会被销毁。

那么,换句话说,我如何创建这种情况,以便我知道onCleared被调用并且我可以验证它的行为?

android unit-testing android-testing android-viewmodel android-architecture-components

9
推荐指数
3
解决办法
3620
查看次数

用于实例化 ViewModel 的首选 Fragment 生命周期方法

android-architecture-components/GithubBrowserSample 存储库中,Fragment#onViewCreated生命周期方法用于ViewModel实例化(具有Fragment范围),用于Fragment使用数据绑定 + LiveData+组合的s ViewModel

来自SearchFragment.kt该回购 ^:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        searchViewModel = ViewModelProviders.of(this, viewModelFactory)
        ...
    }
Run Code Online (Sandbox Code Playgroud)

是否有任何官方的指南或共识哪个这些Fragment生命周期方法,如onAttachonCreateonViewCreated,或者onActivityCreated是实例化的最佳/最安全的地方FragmentViewModel使用ViewModelProviders.of(fragment, viewModelFactory)方法?(考虑到数据绑定 +LiveData组合,如果这有区别的话)

试图理解将ViewModel实例化放入任何早期生命周期方法(例如onAttach/ )的一般优点/缺点onCreatesuper当然是在调用之后)。

提前致谢。

android android-fragments android-livedata android-viewmodel android-architecture-components

9
推荐指数
2
解决办法
3051
查看次数