我试图使用Android双向databinding同checkBox在一个片段。
我有多个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不再选中,复选框的颜色为真但选中图标不存在!以前有人遇到过这个问题吗?
提前致谢
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
当我尝试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) 我有一个 AddressesViewModel 保存用户最喜欢的地址,另一个 SearchViewModel 保存搜索的地址。当用户搜索地址时,我必须通过检查收藏夹数组来检查该地址是否为收藏夹。什么是正确的方法?
我已经尝试从 SearchViewModel 订阅 AddressesViewModel 但我正在寻找其他选项,因为它在这些视图模型之间创建了太多的依赖关系。
我很好奇存储库在MVVM架构中的作用。如果您决定将存储库添加到您的项目中,这个存储库是否只负责来自数据库或网络的数据?问题是关于SharedPreferencesor Files,我应该让存储库对此负责,还是应该将它们保留在ViewModel.
每当您调用.observe()LiveData 时,观察者都会收到该 LiveData 的最后一个值。这在某些情况下可能有用,但对我来说没有用。
每当我调用 时.observe(),我希望观察者只接收未来的 LiveData 更改,而不是.observe()调用时它所持有的值。
对于一个 LiveData 实例,我可能有多个观察者。我希望他们都能在发生 LiveData 更新时收到更新。
我希望每个 LiveData 更新仅被每个观察者使用一次。我认为这只是对第一个要求的重新表述,但我的头已经开始旋转,我对此不确定。
在谷歌搜索这个问题时,我发现了两种常见的方法:
将数据包装在 an 中LiveData<SingleEvent<Data>>并检查该类SingleEvent是否已被消耗。
如果观察者已经获得事件,则扩展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设计:
Repository.delete()RepositoryEvents。因此,当删除完成后,Repository 会通知 ViewModel,ViewModel 也会通知 ListFragment。
现在,当用户切换到第二个 ListFragment 时,会发生以下情况:
android android-lifecycle android-mvvm android-livedata android-architecture-components
我浏览了许多与带有数据绑定的 MVVM 模型相关的博客。由于与 ViewModel 的数据绑定使得编写 junit 测试用例变得容易。
我想知道,我怎么能实现监听器事件一样OnTouchListener,OnClickListener,OnFocusChangeListener在这将使容易编写单元测试用例视图模型数据绑定。
我已经使用黄油刀库进行绑定,并通过它执行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
我一直在研究 MVC/MPV/MVVM 的优缺点,一个共同的主题是 MVC 比 MVP 和 MVVM 更难进行单元测试,但我不完全理解为什么。
根据我目前的理解,在 MVC 中,视图依赖于模型和控制器,因此要测试视图,必须模拟控制器和模型。MVP/MVVM 如何改进?
我有一项活动正在观察存储库中的实时数据。现在,当活动被销毁然后再次创建时,我仍然从存储库中获取旧值,除非我手动获取新值。
为什么即使观察者活动被销毁,可变的实时数据仍保留其旧值?
我正在尝试将 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-mvvm ×10
android ×8
android-architecture-components ×2
mvvm ×2
viewmodel ×2
androidx ×1
button ×1
dagger-2 ×1
data-binding ×1
kotlin ×1
mockito ×1
mvp ×1