标签: android-viewmodel

如何手动清除特定的视图模型?

据我了解,当我们在片段中调用此代码时,我们将从 Activity ViewModelStore 获得一个视图模型实例:

viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)

当fragment结束其生命周期时,该viewmodel的实例将存在于ViewModelStore中,直到activity销毁。ViewModelStore 有一个clear()方法,但它会清除其中的所有视图模型。有什么方法可以清除特定的 ViewModel 吗?

另一个解决方案是将 ViewModel 的范围限定为父片段,但是我们如何通过 ViewModelProviders.of() 初始化另一个片段中的 ViewModel?我应该将片段或视图模型实例传递给下一个片段吗?

android mvvm android-viewmodel

5
推荐指数
1
解决办法
7280
查看次数

使用自定义转换器的两种方式数据绑定

我想将数据绑定与视图模型一起使用,如此处所述

所以这里是摘录:

布局:

    <data class="FragmentEditPersonDataBinding">
    <import type="com.unludo.interview.persons.edit.Converter"/>

    <variable
        name="viewmodel"
        type="com.unludo.interview.persons.edit.PersonEditViewModel" />
   [...]
                 <EditText
                android:id="@+id/editBirthday"
                android:inputType="date"
                android:text="@={Converter.dateToString(viewmodel.birthday)}"
Run Code Online (Sandbox Code Playgroud)

转换器:

object Converter {
    @InverseMethod("stringToDate")
    @JvmStatic
    fun dateToString(
            view: EditText, oldValue: String,
            value: Date
    ): String {
        val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE)

        return sdf.format(value)
    }

    @JvmStatic   
    fun stringToDate(
            view: EditText, oldValue: String,
            value: String
    ): Date {
        val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE)

        return sdf.parse(value)
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型:

class PersonEditViewModel {
    var birthday: Date = GregorianCalendar(1993, 5, 19).time
    ...
Run Code Online (Sandbox Code Playgroud)

现在我在构建时收到此错误:

e: [kapt] An exception …
Run Code Online (Sandbox Code Playgroud)

android android-databinding android-viewmodel android-architecture-components

5
推荐指数
1
解决办法
1618
查看次数

LiveData,注册观察者时如何避免第一次回调

我想在片段中加载任务,在片段的onViewCreated中,我注册观察者LiveData,在片段的onResume中,我异步加载任务,当第一次进入片段时,它工作正常,但是当我导航到其他片段然后返回任务时片段,回调onChanged()将被调用两次。

我知道如果LiveData已经有数据集,它会被传递给观察者,所以当回到任务片段时,onChanged会在注册观察者时触发onViewCreated,而在onResume中,会触发onChanged第二次,我想知道如何避免这种情况。我查了很多,知道有一个EventWrapper,可以标记 onChanged 第一次触发时消耗的内容。但我觉得这种做法太重了。抱歉我的英语不好...

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle 
   savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //...
    mainViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
    mainViewModel.increaseTaskList.observe(getViewLifecycleOwner(), new 
    Observer<List<Task>>() {
        @Override
        public void onChanged(@Nullable List<Task> tasks) {
            Log.d("ZZZ","data changed,IncreaseTaskListAdapter setData");
            adapter.setData(tasks);
        }
    });
}

@Override
public void onResume() {
    super.onResume();
    mainViewModel.loadIncreasePointTaskList();
}
Run Code Online (Sandbox Code Playgroud)

android fragment android-livedata android-viewmodel

5
推荐指数
1
解决办法
5418
查看次数

使用Livedata时如何为RecyclerView使用Filter SearchView?

我有一个RecyclerView。我想用 SearchView 让它可以过滤。我的应用程序基于Android Architecture Components.

我创建了一个过滤方法searchView。当我搜索某些内容时,它可以工作,但是当我清除其中的文本时searchView,列表不会更改,并且仍然显示搜索数据。

活动:

    private StudentAdapter mAdapter;

    mAdapter = new StudentAdapter(this);
    recyclerView.setAdapter(mAdapter);

    //ViewModel
    StudentViewModelFactory factory = new StudentViewModelFactory(mDb, mClassId);
    StudentViewModel viewModel = ViewModelProviders.of(this, factory).get(StudentViewModel.class);
    viewModel.getStudentEntries().observe(this, studentEntries -> mAdapter.setStudents(studentEntries));

    //SearchView
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
    @Override
    public boolean onQueryTextSubmit(String query){
            return false;
    }

    @Override
    public boolean onQueryTextChange(String newText){
            mAdapter.getFilter().filter(newText);
            return false;
    }
    });
Run Code Online (Sandbox Code Playgroud)

适配器:

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.itemHolder> {

    private List<StudentEntry> mStudentEntries;
    private List<StudentEntry> filteredStudentEntries;

    public StudentAdapter(Context context) {
        this.context = context; …
Run Code Online (Sandbox Code Playgroud)

android searchview android-recyclerview android-livedata android-viewmodel

5
推荐指数
1
解决办法
2173
查看次数

访问“Activity”内的“ViewModel”,范围仅限于导航图

在里面Activity你可以得到这样的ViewModel范围Activity

val viewModel = ViewModelProviders.of(this)[ViewModel::class.java] //deprecated way
val viewModel = ViewModelProvider(this)[ViewModel::class.java]
//or
val viewModel by viewModels<ViewModel>()
Run Code Online (Sandbox Code Playgroud)

同样,在 a 中Fragment你可以得到 a ViewModelby

//scoped to parent Activity
val viewModel: ViewModel by activityViewModels()

//scoped to parent Fragment
val viewModel: ViewModel by viewModels({ requireParentFragment() })

//scoped to navigation graph
val viewModel: ViewModel by navGraphViewModels(R.id.login_graph)
Run Code Online (Sandbox Code Playgroud)

现在,如果我尝试访问范围为导航图的ViewModel内部Activity,则没有辅助方法,所以我必须这样做

val viewModel by lazy {
    ViewModelProvider(findNavController(R.id.nav_host_fragment)
            .getViewModelStoreOwner(R.id.your_graph).viewModelStore,
            ViewModelProvider.AndroidViewModelFactory.getInstance(application)
    ).get(ViewModel::class.java)
}
Run Code Online (Sandbox Code Playgroud)

有没有我错过的辅助方法?我必须通过导航图范围访问它吗?我可以只使用Activity范围来访问相同的吗ViewModel

android android-viewmodel android-architecture-navigation

5
推荐指数
0
解决办法
787
查看次数

Android:使用协程进行片状 ViewModel 单元测试

我有一个虚拟机,例如

class CityListViewModel(private val repository: Repository) : ViewModel() {
    @VisibleForTesting
    val allCities: LiveData<Resource<List<City>>> =
        liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) {
            emit(Resource.Loading())
            emit(repository.getCities())
        }
}
Run Code Online (Sandbox Code Playgroud)

我的测试是:

@ExperimentalCoroutinesApi
class CityListViewModelTest {
    @get:Rule
    val rule = InstantTaskExecutorRule()
    @get:Rule
    val coroutineTestRule = CoroutinesTestRule()

    @Test
    fun `allCities should emit first loading and then a Resource#Success value`() =
        runBlockingTest {
            val fakeSuccessResource = Resource.Success(
                listOf(
                    City(
                        1,
                        "UK",
                        "London",
                        Coordinates(34.5, 56.2)
                    )
                )
            )
            val observer: Observer<Resource<List<City>>> = mock()
            val repositoryMock: Repository = mock()

            val sut …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-testing android-viewmodel kotlin-coroutines

5
推荐指数
1
解决办法
1391
查看次数

DataBindingUtil 将布局膨胀为 null

我正在使用 Android Jetpack 导航组件开发单个活动应用程序。在其中一个片段上,我使用了内置的数据绑定工具。奇怪的是,尽管它在前一周还可以工作,但今天却无缘无故地彻底坏了。

\n\n

设置:
\n我与绑定一起使用的片段具有以下布局文件:

\n\n
<?xml version="1.0" encoding="utf-8"?>\n<layout \n    xmlns:android="http://schemas.android.com/apk/res/android"\n    xmlns:app="http://schemas.android.com/apk/res-auto"\n    xmlns:tools="http://schemas.android.com/tools">\n\n    <data>\n    </data>\n\n    <ScrollView\n        android:layout_width="match_parent"\n        android:layout_height="match_parent"\n        android:id="@+id/example_layout_root"\n        tools:context=".example.ExampleFragment"\n        android:background="@color/main_1"\n        >\n\n        ...\n\n    </ScrollView>\n</layout>\n
Run Code Online (Sandbox Code Playgroud)\n\n

我已经删除了主要内容,但它显示我有一个<layout>元素作为根,同时定义了数据和片段布局部分。

\n\n

片段代码如下:

\n\n
class ExamleFragment : Fragment() {\n\n    private val viewModel: ExampleViewModel by sharedViewModel()\n\n    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {\n        // Inflate the layout for this fragment\n        val binding : FragmentExampleBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_example, container, false)\n        // This one also does not work\n        // val binding …
Run Code Online (Sandbox Code Playgroud)

android android-layout android-fragments android-databinding android-viewmodel

5
推荐指数
2
解决办法
6023
查看次数

从 Room DB 获取单个项目。从视图模型调用该函数

所以我的一般问题是如何从 @Query 的视图模型调用函数,您必须传递一些内容然后返回一些内容。我的简单例子:

DAO

@Query ("SELECT * FROM table_name WHERE id = :id LIMIT 1")
fun getItemById (id: Long) : MyItem
Run Code Online (Sandbox Code Playgroud)

回购协议

fun getItemById (id: Long) : MyItem {
return itemDao.getItemById(id)
}
Run Code Online (Sandbox Code Playgroud)

我知道它不能也不应该在 ui 线程上完成。为了插入和删除项目,我使用 viewModelScope 作业,但我不能(也许只是不知道如何)使用它来返回任何内容。如果我将它作为 LiveData 返回到任何地方,那么它的工作原理就像这样:

视图模型

fun itemById(id: Long): LiveData<MyItem> {
 return itemRepo.getItemById(id)
}
Run Code Online (Sandbox Code Playgroud)

然后我在片段/活动中观察它:

viewModel.itemById(id).observe(this, Observer {
 // using it
})
Run Code Online (Sandbox Code Playgroud)

问题是,我真的不需要它成为可观察的实时数据。我只需要拿到一次,检查一下状况就可以了。所以也许有人可以建议如何做到这一点,而不需要它是实时数据。或者我应该将其保留为实时数据?

android dao kotlin android-room android-viewmodel

5
推荐指数
1
解决办法
6067
查看次数

Android 模拟应用程序内的应用程序上下文

我在创建测试类时遇到问题。基本上我想测试执行网络调用的视图模型类。使用 dagger 注入类网络组件需要上下文参数来检查连接,这是我的视图模型:

class MyViewModel(application: Application): AndroidViewModel(application) {
   @Inject lateinit var network: NetworkService
    init {
        DaggerNetworkComponent.builder().networkModule(NetworkModule(application.applicationContext))
        .build().inject(this)
        network.callNetwork()
    } 
}
Run Code Online (Sandbox Code Playgroud)

测试类是这样的

lateinit var myViewModel: MyViewModel
@Test
fun testMyNetwork() { 
   application =  Mockito.mock(Application::class.java)
   myViewModel = MyViewModel(application)
}
Run Code Online (Sandbox Code Playgroud)

总是application.applicationContext返回 null,然后返回IllegalStateException

有什么解决办法吗?

android unit-testing mockito android-viewmodel

5
推荐指数
1
解决办法
6085
查看次数

无法在 android 中创建 AndroidViewModel 类的实例

我正在尝试使用 Android ViewModel 添加 Room 数据库。我按照此链接进行了相同的https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#13

我遇到了一个例外:

导致:java.lang.RuntimeException:无法创建类 com.example.dailyfaithapp.ViewModels.FavouritesViewModel 的实例

我检查了一些问题和答案,但没有一个对我有用。

这是我的视图模型

public class FavouritesViewModel extends ViewModel {

        public FavouriteRepository mRepository;

        public LiveData<List<Favourites>> mAllFavourites;

    public FavouritesViewModel (Application application) {
            mRepository = new FavouriteRepository(application);
            mAllFavourites = mRepository.getmAllFavourites();
        }

        public LiveData<List<Favourites>> getmAllFavourites() { return mAllFavourites; }

        public void insert(Favourites favourites) { mRepository.insertFavourite(favourites); }

}
Run Code Online (Sandbox Code Playgroud)

我还尝试使用视图模型工厂调用视图模型,但在这里不起作用

public class FavouritesViewModelFactory implements ViewModelProvider.Factory {
    private Application mApplication;
    private String mParam;


    public FavouritesViewModelFactory(Application application) {
        mApplication = application;
    }


    @Override
    public <T extends ViewModel> T …
Run Code Online (Sandbox Code Playgroud)

java android instantiation android-mvvm android-viewmodel

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