Architecture-components-samples: [Question] Using ViewModels in Service

Created on 28 Aug 2017  ·  7Comments  ·  Source: android/architecture-components-samples

Hi,

Everything is great with ViewModel. They work as expected in the Activity and Fragment. Recently I have encountered an need to use the ViewModel in Service.
I'm not sure how exactly to do that.

I found one answer on StackOverFlow: https://stackoverflow.com/questions/44708202/observe-livedata-from-foreground-service
But I want to know what's the best practice to use ViewModel in Service.

Most helpful comment

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.

All 7 comments

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.

My service has a UI, which it displays all the time.
I using ViewModel be still wrong? Can you elaborate more on this?
@florina-muntenescu

How your Service negotiate with the UI?

@MotiBartov it's a https://github.com/google/hover floating tabs

How your Service negotiate with the UI?

Control RemoteViews

class FCMessagingService : FirebaseMessagingService(), LifecycleOwner {

private var fcmTokenUpload: Boolean by Preference(Constant.FCM_TOKEN_UPLOAD, false)

private var customerId: String by Preference(Constant.CUSTOMER_ID, "")

private lateinit var mViewModel: UserViewModel

private val mDispatcher = ServiceLifecycleDispatcher(this)

override fun getLifecycle() = mDispatcher.lifecycle

override fun onCreate() {
    mDispatcher.onServicePreSuperOnCreate()

    mViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(UserViewModel::class.java)
    mViewModel.let(lifecycle::addObserver)
    mViewModel.apply {
        mFcmTokenUpload.observe(this@FCMessagingService, Observer {
            fcmTokenUpload = it
        })
    }
    super.onCreate()
}

override fun onStart(intent: Intent?, startId: Int) {
    mDispatcher.onServicePreSuperOnStart()
    super.onStart(intent, startId)
}

override fun onDestroy() {
    mDispatcher.onServicePreSuperOnDestroy()
    lifecycle.removeObserver(mViewModel)
    super.onDestroy()
}

/**
 * Called when message is received.
 */
override fun onMessageReceived(remoteMessage: RemoteMessage) {
    var msg = Messaging("", "", "", "0")
    //消息
    if (remoteMessage.data.isNotEmpty()) {
        remoteMessage.data.forEach {
            if (it.key == "data") {  // "data": "{\"id\":\"2611620\",\"type\":\"2\"}"
                try {
                    msg = Gson().fromJson(it.value, Messaging::class.java)
                } catch (e: JsonSyntaxException) {
                    e.printStackTrace()
                }
            }
        }
    }
    //通知
    remoteMessage.notification?.let {
        sendNotification(it.title, it.body, msg)
    }
}

//新token 发送给app的服务器,用于定向发送推送消息。
override fun onNewToken(token: String) {
    mViewModel.setRegId(customerId, token)
}

}

Can't use this - "mFcmTokenUpload.observe(this@FCMessagingService, Observer "
because for observer, we need main thread to run. And FCM runs on worker thread.

Was this page helpful?
0 / 5 - 0 ratings