标签: android-viewmodel

努力获取相同的 ViewModel 实例

我不确定我是否ViewModel正确理解 Android 中的架构。我认为 ViewModel 生命周期与活动相关,因此我们期望相同的实例,并且如果我们将活动或片段上下文传递给ViewModelProvider?

无论如何,这是我的 ViewModel:

class MainViewModel : ViewModel() {
    var teamName: String = "Warriors";
}
Run Code Online (Sandbox Code Playgroud)

这是我的活动:

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

        viewModel.teamName = "Cavaliers";
        Log.d("YouQi", "activity viewModel.teamName: ${viewModel.teamName}");

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                    .replace(R.id.container, MainFragment.newInstance())
                    .commitNow()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后这是我的片段:

class MainFragment : androidx.fragment.app.Fragment() {
    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-viewmodel

4
推荐指数
1
解决办法
3059
查看次数

在前台服务中实现 Room 时的 ViewModel

我目前有一个应用程序,其中包含用于所有服务器/API 交互的 ForegroundService 和用于本地持久性的 Room 数据库。我一直在尝试实现 AndroidViewModel 来帮助数据持久化和快速 UI 刷新。

然而,根据文档,ViewModels 不能在 Services 中实现,到目前为止,我已经使用 Service 在本地更新信息并使用 LocalBroadcasts 通知组件(这是我想使用 ViewModels 和 Observers 消除的)。

我需要让服务运行,因为应用程序需要在后台继续运行(它是一个关键任务应用程序,应用程序关闭意味着用户将无法提供关键服务),并定期更新某些信息(附近的请求等)。

所以要问核心问题——

  1. 如何将服务与 ViewModel 分开,如果服务具有来自服务器的最新同步数据,如何更新 ViewModel 中的(可变)LiveData 列表?
  2. 这篇文章对 SO 问题的回答 说最好将 ViewModel 与存储库分开,而另一篇文章则给出了在 ViewModel 中包含 Room 数据库的示例。哪个是更好的选择?

我的一些ViewModel代码如下:

 public class HouseCallViewModel extends AndroidViewModel {

        private String TAG = HouseCallViewModel.class.getSimpleName();

        private MutableLiveData<List<HouseCall>> housecallList;
        private MutableLiveData<List<HouseCall>> openHousecalls, confirmedHousecalls, closedHousecalls, missedHousecalls, userCancelledHousecalls, respCancelledHousecalls;
        private MutableLiveData<List<Incident>> incidentList, openIncidents;
        private MutableLiveData<List<Incident>> closedIncidents, usercancelIncidents, respcancelIncidents;
        RevivDatabase database; …
Run Code Online (Sandbox Code Playgroud)

android mvvm android-service android-viewmodel

4
推荐指数
1
解决办法
2970
查看次数

Room 和 ViewModel,多个查询?

所以我有一个带有 Room 数据库的 Android 应用程序,这个后端由一个充当存储库的类管理,该存储库为我的视图模型提供数据,然后我的活动(片段)观察视图模型(每个人都还在我身边吗?)在我的一个片段中,我想获取数据库中点击值高于 X 的所有卡片(实体)的列表,但我也想获取所有标记为收藏夹的卡片,无论其点击值如何。

我当前的解决方案是通过我的存储库从我的视图模型运行 2 个单独的查询,并且我的活动观察这两个查询并组合返回给它的列表,这无法正常工作,因为我的列表加倍了,而且我没有当观察者在不同时间返回时清除列表的好地方,因为它们是异步的(我将发布所有代码)。

我认为我想要的是以某种方式组合查询,以便我只管理一个列表,但我的 SQL 知识不是很好,我不确定这是否可能,或者我可以以某种方式将这些列表合并到我的存储库类中但因为我正在使用实时数据,所以我不确定如何安全地获取数据来组合列表,但也许有一个我不知道的更好的解决方案,但我将在下面发布我正在做的事情

DAO 查询 这是我运行的两个查询,一个查询所有卡片被点击 x 次,另一个查询所有标记为收藏的卡片,两者都采用目前不相关的搜索字符串

@Query("SELECT * FROM card WHERE cardFavourite AND cardWord LIKE :searchWord ORDER BY cardWord ASC")
LiveData<List<Card>> searchFavourites(String searchWord);

@Query("SELECT * FROM card WHERE cardClicked >= :clicks AND cardKeyStage <= :keystage  AND cardWord LIKE :searchWord ORDER BY cardFavourite ASC, cardClicked DESC, cardWord ASC")
LiveData<List<Card>> searchCardListRecents(String searchWord,int clicks, int keystage);
Run Code Online (Sandbox Code Playgroud)

存储库我的存储库是一个充满对数据库的调用的类,这些数据库将实时数据返回到其视图模型,所需的内容是:

public LiveData<List<Card>> searchFavouriteCards(String searchString){
    return cardDao.searchFavourites(searchString);
}

public LiveData<List<Card>> searchRecentCards(String searchString, int clicks){ …
Run Code Online (Sandbox Code Playgroud)

android android-room android-livedata android-viewmodel

4
推荐指数
1
解决办法
8722
查看次数

我应该将 viewModelScope.coroutineContext 传递给 liveData 构建器函数吗?

viewModelScope用于将协程生命周期绑定到ViewModel生命周期。liveData构建器创建一个LiveData运行协程的 ,其生命周期与状态绑定LiveData,因此,当LiveData不活动时,协程会在超时后取消。由于超时,协程不会在配置更改时被取消。

如果我在 a 内创建一个LiveDatavia构建器,并观察到,生命周期已经绑定到生命周期。我还应该将其传递给构建者吗?我认为我不应该,但在 Android 文档示例之一中它通过了:liveDataViewModelLiveDataActivityLiveDataActivityviewModelScope.coroutineContextliveData

class MyViewModel: ViewModel() {
    private val userId: LiveData<String> = MutableLiveData()
    val user = userId.switchMap { id ->
        liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) {
            emit(database.loadUserById(id))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

android android-livedata android-viewmodel android-architecture-components kotlin-coroutines

4
推荐指数
1
解决办法
2495
查看次数

从 LiveData(房间数据库)填充 Spinner

我在哪里

我正在尝试使用 Room 用数据库中的数据填充微调器。数据是一个术语列表,这些术语具有与之关联的课程。

我想在创建新课程时使用微调器来选择与之关联的术语。

目前,微调器不显示默认选项,但如果您单击微调器,它会显示可供选择的数据列表。从微调器中选择某些内容后,它不会显示您选择的内容。

选择之前/之后的微调器

显示可用选项的微调器

这是我将数据加载到微调器适配器的代码:

        termsList = new ArrayList<>();
        termIdList = new ArrayList<>();
        mTermViewModel = new ViewModelProvider(this).get(TermViewModel.class);
        mTermViewModel.getAllTerms().observe(this, new Observer<List<TermEntity>>() {
            @Override
            public void onChanged(@Nullable final List<TermEntity> terms) {
                for (TermEntity term : terms) {
                    termsList.add(term.getTermName());
                    termIdList.add(term.getTermId());
                }
            }
        });

        ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, termsList);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mTermSpinner.setAdapter(adapter);
    }
Run Code Online (Sandbox Code Playgroud)

这是 TermDAO

@Dao
public interface TermDAO {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(TermEntity term);

    @Query("DELETE FROM terms")
    void deleteAllTerms();

    @Query("SELECT * FROM terms ORDER BY termId ASC")
    LiveData<List<TermEntity>> getAllTerms(); …
Run Code Online (Sandbox Code Playgroud)

android dao android-spinner android-room android-viewmodel

4
推荐指数
1
解决办法
3200
查看次数

Android:如何根据视图模型实时数据属性为片段编写单元测试?

我的片段 UI 中有一个列表视图,它的元素设置取决于来自视图模型 LiveData 属性的值的状态。

我想为片段创建工具测试,该片段包含与该属性的值集相关的 3 个场景测试用例,但我不知道从哪里开始。

我的代码应该如下所示:

class MyViewModel : ViewModel() {
var status = MutableLiveData("")
}


class MyFragment : Fragment() {

private lateinit var myViewModel: MyViewModel

private lateinit var myListView: ListView

override fun onAttach(context: Context) {
    AndroidSupportInjection.inject(this)
    super.onAttach(context)

    myViewModel =
        ViewModelProviders.of(this, ViewModelProvider.Factory).get(MyViewModel::class.java)
}

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {

    when (myViewModel?.status) {

        "status1":
            setListContent(items1)

        "status1":
            setListContent(items2)

        "status1":
            setListContent(items3)

        else
            setListContent
        (items1)

    }
}

private fun setListContent(itemsList: List<?>) {
    myListView.adapter = MyCustomadapter(context!!, …
Run Code Online (Sandbox Code Playgroud)

android unit-testing kotlin android-livedata android-viewmodel

4
推荐指数
1
解决办法
5433
查看次数

AndroidViewModel 实例化而不传递应用程序上下文?

我目前正在研究Android Room with a View示例应用程序,这里提供完整的源代码。在这个项目中,定义了一个WordViewModel类型AndroidViewModel

class WordViewModel(application: Application) : AndroidViewModel(application)
Run Code Online (Sandbox Code Playgroud)

请注意构造函数如何要求Application传入一个实例。然而,当我检查 时MainActivityWordViewModel检索了 而不传入 Application实例:

// Get a new or existing ViewModel from the ViewModelProvider.
mWordViewModel = new ViewModelProvider(this).get(WordViewModel.class);
Run Code Online (Sandbox Code Playgroud)

这怎么可能,如何在WordViewModel不传入Application实例和不使用自定义工厂的情况下检索?

android android-viewmodel android-architecture-components

4
推荐指数
1
解决办法
3163
查看次数

使用 SavedStateHandle 加入 sharedViewModel

我有单个活动应用程序和片段数量。其中一些片段正在使用我的视图模型,通常是这样的:

private val myViewModel: MyViewModel by sharedViewModel()
Run Code Online (Sandbox Code Playgroud)

如果我想同时拥有模型shared并使用 SavedStateHandle 保持其状态怎么办?我无法弄清楚这是否受支持,如果是,则需要如何使用它(在托管活动中将 viewmodel 声明为 stateViewModel 不起作用)。

android android-mvvm android-viewmodel koin androidx

4
推荐指数
1
解决办法
1959
查看次数

Dagger-Hilt @ViewModelInject sharedViewModel 未注入片段

我正在尝试使用Jetpack 教程在片段和活动之间创建共享注入视图模型。

共享视图模型成功注入到父 MyActivity 中,但是当子渲染时,由于依赖注入失败,应用程序崩溃。我在下面提供了创建问题的代码。

提供会话管理器:

@InstallIn(ApplicationComponent::class)
@Module
class AppModule {
    @Provides
    @Singleton
    fun provideSessionManager(
        networkClient: NetworkClient
    ): SessionManager {
        return SessionManager(networkClient)
    }
}
Run Code Online (Sandbox Code Playgroud)

要注入共享视图模型:

class SharedViewModel @ViewModelInject constructor(
    private var sessionManager: SessionManager
) : ViewModel() {

    var name = MutableLiveData<String>("Shared View Model")
}
Run Code Online (Sandbox Code Playgroud)

并且由父活动和子片段使用。

class MyActionFragment() : Fragment() {
    private val viewModel: SharedViewModel by viewModels()
    override fun onActivityCreated(savedInstanceState: Bundle?) {
       super.onActivityCreated(savedInstanceState)
       Timber.d("View Model Name 1: ${viewModel.name.value}") // This line crashes
    }
}
Run Code Online (Sandbox Code Playgroud)
class MyActivity : AuthenticatedBaseActivity() { …
Run Code Online (Sandbox Code Playgroud)

android android-fragments android-viewmodel dagger-hilt

4
推荐指数
3
解决办法
5488
查看次数

如何使用 Hilt 将安全参数注入视图模型?

在这里找到了一个类似的问题。在撰写此问题时,只有此答案可用,这对我没有任何帮助,我相信对提出问题的人也没有任何帮助。

我检查了答案中链接的 repo,它通过在 viewmodel 中创建一个 init 方法并在 Activity/Fragment 中调用它来“解决”问题。

由于viewmodel已经被注入,这个方案对我来说似乎不太理想,我想知道在使用hilt时是否还有其他可用的选项。

android dependency-injection android-viewmodel android-jetpack-navigation dagger-hilt

4
推荐指数
1
解决办法
1358
查看次数