Почему LiveData медленный - PullRequest
2 голосов
/ 15 мая 2019

В моем приложении я загружаю данные из локальной базы данных, и это очень медленно.Я попытался найти то, что медленно, и я обнаружил, что это происходит из-за LiveData.

Я создал пример приложения для проверки скорости LiveData. Вот мой тестовый код: 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()
}
}

Если я запускаю этот фрагмент, яполучил их в LogCat:

2019-05-15 13: 23: 07.405 8632-8632 / liveatatest D / FirstFragment: onCreateView с именем

2019-05-15 13:23: 07.406 8632-8632 / жилатестат D / FirstFragment: обратный вызов dataLoaded

2019-05-15 13: 23: 07.438 8632-8632 / жилатестат D / FirstFragment: событие dataLoaded

2019-05-15 13: 23: 07.439 8632-8632 / aliveatatest D / FirstFragment: событие dataLoaded2

Вы можете видеть, что dataLoadedEvent.postValue(null) занимает не менее 30 мс, но простой обратный вызов вызывается немедленно.

Есть ли какое-нибудь решение для ускорения событий LiveData?

1 Ответ

3 голосов
/ 15 мая 2019

Вы видите, что dataLoadedEvent.postValue (null) занимает не менее 30 мс

postValue() предназначено для обновления MutableLiveData из фонового потока. Под обложками он использует Handler для направления вашего события в основной поток приложения. Следовательно, будет некоторая задержка, так как обрабатываются события других очередей рабочих потоков основного приложения.

Это также показывает, что ваш эталонный тест некорректен («сравнение яблок с апельсинами»). Или:

  • Используйте Handler вместо обратного вызова (или какой-либо другой подход "запустить этот код в главном потоке приложений") или

  • Используйте setValue() (или value=, поскольку вы находитесь в Kotlin) вместо postValue(), чтобы обновить содержимое MutableLiveData непосредственно в главном потоке приложения

...