Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why LiveData is slow

In my application, I load data from the local database and it's very slow. I tried to find what is slow and I found that this occurs because of LiveData.

I created a sample application to test LiveData speed here you are my test code: FirstFragment:

class FirstFragment : Fragment(), FirstFragmentCallback {
private val TAG = FirstFragment::class.java.simpleName

private var mViewModel: FirstFragmentViewModel? = null


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mViewModel = ActivityUtils.obtainViewModel(requireActivity(), FirstFragmentViewModel::class.java)
    (mViewModel as FirstFragmentViewModel).callback = this
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val v = inflater.inflate(R.layout.first_fragment, container, false)
    Log.d(TAG, "onCreateView called")

    registerObservables()
    mViewModel?.loadData()
    return v
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val secondFragmentButton = view.findViewById<Button>(R.id.second)
    secondFragmentButton.setOnClickListener {
        ActivityUtils.replaceFragmentInActivity(requireFragmentManager(), SecondFragment(), R.id.container, false)
    }
}

private fun registerObservables(){
    mViewModel?.dataLoadedEvent?.observe(this, Observer {
        Log.d(TAG, "dataLoaded event")
    })
    mViewModel?.dataLoaded2Event?.observe(this, Observer {
        Log.d(TAG, "dataLoaded2 event")
    })
}

override fun dataLoaded() {
    Log.d(TAG, "dataLoaded callback")
}
}

FirstFragmentViewModel:

class FirstFragmentViewModel(val mAppliction: Application): AndroidViewModel(mAppliction) {

val dataLoadedEvent: SingleLiveEvent<Void> = SingleLiveEvent()

val dataLoaded2Event: MutableLiveData<Void> = MutableLiveData()

var callback: FirstFragmentCallback? = null

fun loadData(){
    dataLoadedEvent.postValue(null)
    dataLoaded2Event.postValue(null)
    callback?.dataLoaded()
}
}

If I run this fragment I got these in the LogCat:

2019-05-15 13:23:07.405 8632-8632/livedatatest D/FirstFragment: onCreateView called

2019-05-15 13:23:07.406 8632-8632/livedatatest D/FirstFragment: dataLoaded callback

2019-05-15 13:23:07.438 8632-8632/livedatatest D/FirstFragment: dataLoaded event

2019-05-15 13:23:07.439 8632-8632/livedatatest D/FirstFragment: dataLoaded2 event

You can see that dataLoadedEvent.postValue(null) take at least 30ms, but the simple callback is called immediately.

Is there any solution to speed up LiveData events?

like image 527
just Avatar asked May 15 '19 11:05

just


1 Answers

You can see that dataLoadedEvent.postValue(null) take at least 30ms

postValue() is for when you want to update the MutableLiveData from a background thread. Under the covers, it uses a Handler to route your event to the main application thread. Therefore, there will be some delay, as other main application thread work queue events get processed.

It also illustrates that your benchmark is flawed ("comparing apples to oranges"). Either:

  • Use Handler instead of a callback (or some other "run this code on the main application thread" approach), or

  • Use setValue() (or value= since you are in Kotlin) instead of postValue(), to update the MutableLiveData content directly on the main application thread

like image 66
CommonsWare Avatar answered Oct 11 '22 06:10

CommonsWare