在android中的模块之间共享ViewModel实例

问题描述 投票:0回答:2

我正在研究 MVVM 架构。我想在我的 Android 应用程序中的模块之间共享视图模型的实例。当用户从应用程序模块完成骑行时,我想访问我的聊天模块视图模型实例以执行一些数据库操作,即清除对话实体等。我正在使用带有视图模型的房间数据库。 ChatActivityNew 是聊天模块中的一个 Activity。

App模块预约活动

Dialogs.INSTANCE.showRideStatusDialog(mCurrentActivity, new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Dialogs.INSTANCE.dismissDialog();
        Dialogs.INSTANCE.showLoader(mCurrentActivity);
        ChatActivityNew.setMukamalListener(iMukamalCallback);
        dataRepository.requestEndRide(mCurrentActivity, driversDataHandler);
    }
}

聊天模块ChatActivityNew

/**
 * Set the Mukamal Callback listener & call onMukamal abstract
 * method which takes Message view model as a parameter.
 *
 * @param iMukamalCallback is a callback listener.
 */
public static void setMukamalListener(IMukamalCallback iMukamalCallback) {
    mukamalCallback = iMukamalCallback;
    mukamalCallback.onMukamal(mModel);
}

mModel 为 null,因为 Activity 尚未加载并且 MessageViewModel 为 null,那么我如何访问 MessageViewModel 的实例。

我已经遵循了android开发者文档 https://developer.android.com/topic/libraries/architecture/viewmodel

任何帮助都将非常感激。

编辑

Dialogs.INSTANCE.showRideStatusDialog(mCurrentActivity, new View.OnClickListener() {
    @Override
    public void onClick(View v) {
          Dialogs.INSTANCE.dismissDialog();
          Dialogs.INSTANCE.showLoader(mCurrentActivity);
          EventBus.getDefault().postSticky(
              new MessageEvent(com.example.chatmodule.utils.Constants.RIDE_COMPLETE)
          );
          dataRepository.requestEndRide(mCurrentActivity, driversDataHandler);
        }
    }

聊天模块订阅方式

@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onMessageEvent(MessageEvent event) {
        if (mModel != null && event.message.equalsIgnoreCase(RIDE_COMPLETE)){
            mModel.deleteConversation();
            mModel.deleteMessages();
        }
    }
java android mvvm
2个回答
0
投票

理想情况下,您希望尽可能地解耦这些视图模型。为了实现您想要做的事情,您需要一个事件聚合器机制。

在您的示例中,您的聊天模块将订阅“NowSave”类型的事件,并且您的应用程序模块在需要保存数据时将发布“NowSave”类型的事件。

在 Android 世界中,

EventBus
看起来像是用于这种机制的流行库: http://greenrobot.org/eventbus/


0
投票

O找到了两种方法来做到这一点

#1 - 将 viewModel 的字段存储在伴随对象中。

这样所有实例都将访问相同的数据 优点

  • viewModel 可以通过通常的方式创建,“通过activityViewModels()” 或“通过 viewModels()”:

private val sharedViewModel: SharedViewModel by viewModels()
or
private val sharedViewModel: SharedViewModel by activityViewModels()

缺点

  • 将创建 viewModel 的两个(或更多)实例

#2 - 创建您自己的“ViewModelFactory” 这样您就可以控制它的创建,并作为单个实例提供 优点

  • 只会创建一个 viewModel 实例

缺点

  • 无法使用SavedStateHandle
  • 获取viewModel实例的方式稍微费力一点:

lateinit var sharedViewModelFactory :  SharedViewModelFactory
private lateinit var sharedViewModel: SharedViewModel
...
sharedViewModel = ViewModelProvider(this,sharedViewModelFactory).get(SharedViewModel::class.java)

创建工厂的代码如下:

package ...login.data.dependencyInjection

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
...
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.scopes.ActivityScoped
import dagger.hilt.components.SingletonComponent
import javax.inject.Inject
import javax.inject.Scope
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
class SharedViewModelModule {

    @Singleton
    @Provides
    fun provideViewModelInstanceHolder(): ViewModelInstanceHolder {
        return ViewModelInstanceHolder()
    }

    @Singleton
    @Provides
    fun provideUserViewModelFactory(
        viewModelInstanceHolder: ViewModelInstanceHolder
    ): SharedViewModelFactory {
        return SharedViewModelFactory(
            viewModelInstanceHolder
        )
    }
}

class ViewModelInstanceHolder() {
    companion object {
        var sharedViewModel: SharedViewModel? = null
    }

    fun getInstance(): SharedViewModel {
        if (sharedViewModel == null) {
            sharedViewModel = SharedViewModel()
        }
        return sharedViewModel!!
    }
}

class SharedViewModelFactory @Inject constructor(private val viewModelInstanceHolder: ViewModelInstanceHolder) :
    ViewModelProvider.NewInstanceFactory() {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return viewModelInstanceHolder.getInstance() as T
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.