Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access viewModel inside a service in android

how we can initialize the viewModel in a service. in a fragment, we do that with Kotlin delegate "by activityViewModels". or we can do it with the ViewModelProvider().get. but as far as I find out we can not do it in service because we need a "ViewModelStoreOwner" like activity or fragment.

so is that even a best practice to initialize a ViewModel in a service?

my project here.

like image 463
imansdn Avatar asked Jul 11 '20 11:07

imansdn


Video Answer


2 Answers

It is not recommended using a ViewModel in a service. You could call your repository from your service itself.

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

The ViewModel should be used closely with an Activity or a Fragment, so it's destined to live in the UI layer of your application. Therefore, I don't recommend using the ViewModel in a Service. Create a different class, that would be used in the Service and, if needed, in the ViewModel. Like this you ensure the separation of concerns and avoid giving the ViewModel more responsibilities than needed.

like image 130
Saurabh Thorat Avatar answered Oct 16 '22 16:10

Saurabh Thorat


define a base service, then you can using ViewModel like activity/fragment

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()));
    }
}

extend the above class, show an overlay window in service

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);
        }
    }
}
like image 2
Yessy Avatar answered Oct 16 '22 16:10

Yessy