在android中的服务中访问viewModel

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

我们如何在service中初始化viewModel。 在片段中,我们使用 Kotlin 委托“by ActivityViewModels”来完成此操作。 或者我们可以使用 ViewModelProvider().get 来完成。 但据我发现,我们无法在服务中执行此操作,因为我们需要一个“ViewModelStoreOwner”,例如活动或片段。

这就是在服务中初始化 ViewModel 的最佳实践吗?

我的项目在这里

android mvvm service viewmodel repository-pattern
3个回答
17
投票

不建议在服务中使用 ViewModel。您可以从您的服务本身调用您的存储库。

https://github.com/android/architecture-components-samples/issues/137#issuecomment-327854042

ViewModel 应与 Activity 或 Fragment 紧密结合使用, 所以它注定存在于应用程序的 UI 层中。 因此,我不建议在 Service 中使用 ViewModel。创造 一个不同的类,将在服务中使用,如果需要, 在视图模型中。这样你就可以确保关注点和关注点的分离 避免赋予 ViewModel 过多的职责。


5
投票

定义一个基础服务,然后你就可以像activity/fragment一样使用ViewModel

public class LifecycleAndViewStoreOwnerService extends LifecycleService implements ViewModelStoreOwner, HasDefaultViewModelProviderFactory {

    final ViewModelStore mViewModelStore = new ViewModelStore();
    ViewModelProvider.Factory mFactory;

    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        return mViewModelStore;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
                if (source.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
                    mViewModelStore.clear();
                    source.getLifecycle().removeObserver(this);
                }
            }
        });
    }

    @NonNull
    @Override
    public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
        return mFactory != null ? mFactory : (mFactory = new ViewModelProvider.AndroidViewModelFactory(getApplication()));
    }
}

扩展上面的类,在服务中显示一个覆盖窗口

public class MyLifecycleService extends LifecycleAndViewStoreOwnerService {

    private static final String TAG = "MyLifecycleService";

    @Override
    public void onCreate() {
        super.onCreate();
        final OverlayWindowBinding binding = OverlayWindowBinding.inflate(LayoutInflater.from(this));
        binding.setViewModel(new ViewModelProvider(this).get(ViewModel.class));
        binding.setLifecycleOwner(this);

        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        getSystemService(WindowManager.class).addView(binding.getRoot(), layoutParams);

        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
                if (source.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
                    getSystemService(WindowManager.class).removeViewImmediate(binding.getRoot());
                    source.getLifecycle().removeObserver(this);
                }
            }
        });
    }

    public static class ViewModel extends AndroidViewModel {
        public ViewModel(@NonNull Application application) {
            super(application);
        }
    }
}

0
投票

我允许自己插入我的五分钱:我使用jetpack compose从前台服务+柄进行叠加绘制(是的,这是一种现代方式)。所以,我希望

hiltViewModel
-compose 能够工作,但它没有;)结果我开始手动创建一个 viewModel,就像 ActivityViewModel 一样。这是我的愿景的一个例子,可能有人会发现它有帮助:

abstract class AdvancedLifecycleService : LifecycleService(), SavedStateRegistryOwner, ViewModelStoreOwner {
    protected abstract val savedStateRegistryController: SavedStateRegistryController

    override val savedStateRegistry: SavedStateRegistry
        get() = savedStateRegistryController.savedStateRegistry

    override val viewModelStore: ViewModelStore = ViewModelStore()

    @Inject
    lateinit var overlayViewModelProvider: Provider<OverlayViewModel>

    override fun onCreate() {
        super.onCreate()
        savedStateRegistryController.performRestore(null)
        lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) {
                    viewModelStore.clear()
                    source.lifecycle.removeObserver(this)
                }
            }
        })

        val a = ViewModelProvider(
            store = viewModelStore,
            factory = ForegroundViewModelFactory(
                overlayViewModelProvider = overlayViewModelProvider,
            ),
            defaultCreationExtras = CreationExtras.Empty
        )[OverlayViewModel::class.java]
        val b = ViewModelProvider(
            store = viewModelStore,
            factory = ForegroundViewModelFactory(
                overlayViewModelProvider = overlayViewModelProvider,
            ),
            defaultCreationExtras = CreationExtras.Empty
        )[OverlayViewModel::class.java]
        println("a == b: ${a == b}") // true
    }

    private class ForegroundViewModelFactory(
        private val overlayViewModelProvider: Provider<OverlayViewModel>,
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(OverlayViewModel::class.java)) {
                return overlayViewModelProvider.get() as T
            } else {
                throw IllegalArgumentException("Unknown ViewModel class")
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.