标签: android-mvvm

使用带有复选框的android双向数据绑定

我试图使用Android双向databindingcheckBox在一个片段。
我有多个viewPager带有 custom 的片段,第FragmentStatePagerAdapter一个片段。 我有一个带有以下代码的复选框:viewModelfragment

<CheckBox
            android:id="@+id/checkbox_accept_rules"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:checked="@={viewmodel.isAccept}"
            android:gravity="right"
            android:text="text..." />
Run Code Online (Sandbox Code Playgroud)

在视图模型中:

private final ObservableBoolean isAccept = new ObservableBoolean(false);
Run Code Online (Sandbox Code Playgroud)

当我转到最后一个fragment并返回到第一个时checkBox不再选中,复选框的颜色为真但选中图标不存在!以前有人遇到过这个问题吗?

提前致谢

android viewmodel android-mvvm

7
推荐指数
1
解决办法
2787
查看次数

在 MVVM 活动中模拟 ViewModel

29/04/18 更新

重新命名以提高准确性。问题很简单:ViewModels不能简单地在 Activity 上模拟,因为它们是在 Acitivity 的 onCreate() 中实例化的。解决这个问题的最佳方法是什么?

一些相关的想法位于here(未成功尝试实施)

原始问题

使用 Google 的 MVVM GithubBrowserSample 代码库,我正在尝试进行仪器测试以检查加载状态是否会弹出进度条。具体来说,是UserFragmentTest.loading() 方法的镜像。这是非常简单的事情,我试图将我的设置与 Google 的设置紧密匹配。

但是我可以看到这是不对的。具体来说,当我明确要求它们不在我的测试@Before函数中时,我可以看到正在调用我的 ViewModel (VM) 中的函数。我正在使用 Kotlin、Dagger2 和架构组件。

当我运行UserFragmentTest.loading()测试时,我可以看到代码确实在 VM 中没有调用任何东西(甚至没有调用构造函数)。然而BaseActivity,即使我要求它返回虚拟数据,我的也会调用 VM init 块(设置)和 getUser() 函数。我能看到的唯一主要区别是我的 Activity 和 Google 正在测试 Fragment,而 ViewModel 模拟函数使用 Niek Haarman 的Mockito-Kotlin库。

登录活动测试.kt

@RunWith(AndroidJUnit4::class)
class LoginActivityTest {

    private val email = "***********@gmail.com"
    private val password = "123456"

    @Suppress("MemberVisibilityCanBePrivate")
    @get:Rule
    val activityRule = ActivityTestRule(LoginActivity::class.java) …
Run Code Online (Sandbox Code Playgroud)

mockito kotlin android-espresso android-mvvm android-architecture-components

7
推荐指数
0
解决办法
3838
查看次数

Google SignInButton 的 onClick 无法使用 DataBinding

当我尝试onClick在我的 Google 中设置方法时SignInButton

android:onClick="@{() -> viewModel.onGoogleLoginClick()}"

我总是收到这个错误:

发现数据绑定错误。

****/ 数据绑定错误 ****msg: 找不到正确的 android:onClick 回调类。尝试 android.view.View 但它有 0 个抽象方法,应该有 1 个抽象方法。

文件:/Users/user/Android/project/app/src/main/res/layout/activity_login.xml loc:53:31 - 53:66 ****\ 数据绑定错误****

这是我的代码:

活动登录.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.login.LoginActivity">
    <data>
        <import type="android.view.View" />
        <variable
            name="viewModel"
            type="com.example.myapp.ui.login.LoginViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:padding="@dimen/default_layout_padding">

        <EditText
            android:id="@+id/login_name_editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/login_username_hint"
            android:inputType="text"
            android:text="@{viewModel.mEmail}" />

        <EditText
            android:id="@+id/login_pass_editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/login_name_editText"
            android:hint="@string/login_password_hint"
            android:inputType="numberPassword"
            android:text="@{viewModel.mPassword}" />

        <Button
            android:id="@+id/login_login_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/login_pass_editText"
            android:onClick="@{() -> viewModel.onServerLoginClick()}"
            android:text="@string/login_login_button_text" …
Run Code Online (Sandbox Code Playgroud)

data-binding android button android-mvvm android-livedata

7
推荐指数
2
解决办法
1674
查看次数

如何在另一个 ViewModel 中使用来自一个 ViewModel 的数据

我有一个 AddressesViewModel 保存用户最喜欢的地址,另一个 SearchViewModel 保存搜索的地址。当用户搜索地址时,我必须通过检查收藏夹数组来检查该地址是否为收藏夹。什么是正确的方法?

我已经尝试从 SearchViewModel 订阅 AddressesViewModel 但我正在寻找其他选项,因为它在这些视图模型之间创建了太多的依赖关系。

android viewmodel android-mvvm android-livedata

7
推荐指数
1
解决办法
3720
查看次数

在 MVVM 上使用 SharedPreferences 或 File

我很好奇存储库在MVVM架构中的作用。如果您决定将存储库添加到您的项目中,这个存储库是否只负责来自数据库或网络的数据?问题是关于SharedPreferencesor Files,我应该让存储库对此负责,还是应该将它们保留在ViewModel.

sharedpreferences android-mvvm

7
推荐指数
1
解决办法
3736
查看次数

让每个观察者仅在订阅/观察时接收*新的LiveData

每当您调用.observe()LiveData 时,观察者都会收到该 LiveData 的最后一个值。这在某些情况下可能有用,但对我来说没有用。

  1. 每当我调用 时.observe(),我希望观察者只接收未来的 LiveData 更改,而不是.observe()调用时它所持有的值。

  2. 对于一个 LiveData 实例,我可能有多个观察者。我希望他们都能在发生 LiveData 更新时收到更新。

  3. 我希望每个 LiveData 更新仅被每个观察者使用一次。我认为这只是对第一个要求的重新表述,但我的头已经开始旋转,我对此不确定。


在谷歌搜索这个问题时,我发现了两种常见的方法:

  1. 将数据包装在 an 中LiveData<SingleEvent<Data>>并检查该类SingleEvent是否已被消耗。

  2. 如果观察者已经获得事件,则扩展MediatorLiveData并使用查找映射

这些方法的示例可以在这里找到: https://gist.github.com/JoseAlcerreca/5b661f1800e1e654f07cc54fe87441af#gistcomment-2783677 https://gist.github.com/hadilq/f095120348a6a14251a02aca329f1845#file-liveevent-kt https://gist .github.com/JoseAlcerreca/5b661f1800e1e654f07cc54fe87441af#file-event-kt

不幸的是,这些例子都不能满足我的所有要求。大多数时候,问题是任何新的观察者在订阅时仍然收到最后的 LiveData 值。这意味着每当用户在屏幕之间导航时,已经显示的 Snackbar 就会一次又一次地显示。


为了让您了解我正在谈论的内容/我正在编码的内容:

我遵循Android架构组件的LiveData MVVM设计:

  • 2 ListFragment 显示条目列表。
  • 他们使用同一 ViewModel 类的 2 个实例来观察与 UI 相关的 LiveData。
  • 用户可以删除此类 ListFragment 中的条目。删除是通过 ViewModel 调用完成的Repository.delete()
  • ViewModel 观察 的存储库RepositoryEvents

因此,当删除完成后,Repository 会通知 ViewModel,ViewModel 也会通知 ListFragment。

现在,当用户切换到第二个 ListFragment 时,会发生以下情况:

  • 创建第二个 …

android android-lifecycle android-mvvm android-livedata android-architecture-components

7
推荐指数
1
解决办法
3135
查看次数

如何在 MVVM Android 中使用数据绑定处理 ViewModel 中的 onClick 或 onTouch 之类的事件

我浏览了许多与带有数据绑定的 MVVM 模型相关的博客。由于与 ViewModel 的数据绑定使得编写 junit 测试用例变得容易。

我想知道,我怎么能实现监听器事件一样OnTouchListenerOnClickListenerOnFocusChangeListener在这将使容易编写单元测试用例视图模型数据绑定。

我已经使用黄油刀库进行绑定,并通过它执行OnTouch事件,我的问题是,这是在 Activity 中实现侦听器而不是直接在 ViewModel 中实现它的正确方法吗? 请参考以下代码以了解具有 MVVM 结构的 LoginScreen:

登录ActivityNew.java

public class LoginActivityNew extends AppCompatActivity {

@BindView(R.id.et_password)
AppCompatEditText etPassword;

private LoginViewModel loginViewModel;

ActivityLoginBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

        binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
        loginViewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
        binding.setViewModel(loginViewModel);
        binding.setLifecycleOwner(this);

        ButterKnife.bind(this);

        binding.buttonLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Common common = new Common(getApplicationContext());
                common.isInternetAvailable(LoginActivityNew.this, new Common.InternetStateListener() {
                    @Override
                    public …
Run Code Online (Sandbox Code Playgroud)

android mvvm android-databinding android-mvvm android-viewmodel

7
推荐指数
1
解决办法
1万
查看次数

为什么 MVC 中的单元测试比 MVP 和 MVVM 更难

我一直在研究 MVC/MPV/MVVM 的优缺点,一个共同的主题是 MVC 比 MVP 和 MVVM 更难进行单元测试,但我不完全理解为什么。

根据我目前的理解,在 MVC 中,视图依赖于模型和控制器,因此要测试视图,必须模拟控制器和模型。MVP/MVVM 如何改进?

model-view-controller mvp android mvvm android-mvvm

7
推荐指数
2
解决办法
658
查看次数

即使观察者活动被破坏,MutableLiveData 也会保留旧值

我有一项活动正在观察存储库中的实时数据。现在,当活动被销毁然后再次创建时,我仍然从存储库中获取旧值,除非我手动获取新值。

为什么即使观察者活动被销毁,可变的实时数据仍保留其旧值?

android android-mvvm android-livedata mutablelivedata

7
推荐指数
1
解决办法
5302
查看次数

如何使用 Dagger 2 在 ViewPager 中注入相同 Fragment 的 ViewModel

我正在尝试将 Dagger 2 添加到我的项目中。我能够为我的片段注入 ViewModels(AndroidX 架构组件)。

我有一个ViewPager,它有 2 个相同片段的实例(每个选项卡只有很小的更改),并且在每个选项卡中,我观察LiveData到更新数据更改(来自 API)。

问题在于,当 api 响应到来并更新 时LiveData,当前可见片段中的相同数据将发送给所有选项卡中的观察者。(我认为这可能是因为 的范围ViewModel)。

这是我观察数据的方式:

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

        activityViewModel.expenseList.observe(this, Observer {
            swipeToRefreshLayout.isRefreshing = false
            viewAdapter.setData(it)
        })
    ....
}
Run Code Online (Sandbox Code Playgroud)

我正在使用这个类来提供ViewModels:

class ViewModelProviderFactory @Inject constructor(creators: MutableMap<Class<out ViewModel?>?, Provider<ViewModel?>?>?) :
    ViewModelProvider.Factory {
    private val creators: MutableMap<Class<out ViewModel?>?, Provider<ViewModel?>?>? = creators
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        var creator: Provider<out ViewModel?>? = creators!![modelClass]
        if (creator == …
Run Code Online (Sandbox Code Playgroud)

android android-viewpager dagger-2 android-mvvm androidx

7
推荐指数
1
解决办法
1745
查看次数