【问题标题】:Slow fragment accessing using SharedFragment with `by activityViewModels`?使用带有 `by activityViewModels` 的 SharedFragment 访问缓慢的片段?
【发布时间】:2020-11-22 20:29:58
【问题描述】:

所以,有人告诉我之前在另一个问题 (How do I store a data from a fragment so it can be reuse in a MVVM architecture?) 中使用共享视图模型

下面的代码没有使用共享视图模型,速度更快

package io.github.andraantariksa.cratesio.ui

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import io.github.andraantariksa.cratesio.R
import io.github.andraantariksa.cratesio.data.api.model.CrateSummary.CrateSummary
import io.github.andraantariksa.cratesio.utils.InjectorUtils
import kotlinx.android.synthetic.main.fragment_summary.*
import kotlinx.coroutines.launch


class SummaryFragment : ScopedFragment() {
    private lateinit var viewModelFactory: CratesViewModelFactory
    private lateinit var viewModel: CratesViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_summary, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        viewModelFactory = InjectorUtils.provideCratesViewModelFactory(context!!)
        viewModel = ViewModelProvider(this, viewModelFactory)
            .get(CratesViewModel::class.java)

        viewModel.cratesSummaryLast?.let {
            setupSummaryRecyclerView(it)
        }
        fetchRecyclerViewData()
    }

    private fun fetchRecyclerViewData() {
        launch {
            val crateSummaryLiveData = viewModel.crateSummary.await()
            crateSummaryLiveData.observe(viewLifecycleOwner, Observer {
                setupSummaryRecyclerView(it)
            })
        }
    }

    private fun setupSummaryRecyclerView(crateSummary: CrateSummary) {
        viewModel.cratesSummaryLast = crateSummary

        textViewCratesTotalNum.text = crateSummary.numCrates.toString()
        textViewDownloadsTotalNum.text = crateSummary.numDownloads.toString()

        val newCratesAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.newCrates)
        recyclerViewNewCrates.layoutManager = LinearLayoutManager(context)
        recyclerViewNewCrates.adapter = newCratesAdapter

        val mostDownloadedAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostDownloaded)
        recyclerViewMostDownloaded.layoutManager = LinearLayoutManager(context)
        recyclerViewMostDownloaded.adapter = mostDownloadedAdapter

        val justUpdatedAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.justUpdated)
        recyclerViewJustUpdated.layoutManager = LinearLayoutManager(context)
        recyclerViewJustUpdated.adapter = justUpdatedAdapter

        val mostRecentlyDownloaded =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerViewMostRecentlyDownloaded.layoutManager = LinearLayoutManager(context)
        recyclerViewMostRecentlyDownloaded.adapter = mostRecentlyDownloaded

        val mostPopularKeywords =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerViewPopularKeywords.layoutManager = LinearLayoutManager(context)
        recyclerViewPopularKeywords.adapter = mostPopularKeywords

        val popularCategories =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerPopularCategories.layoutManager = LinearLayoutManager(context)
        recyclerPopularCategories.adapter = popularCategories
    }
}

但是,通过使用shared view model,访问/打开片段变得更慢

package io.github.andraantariksa.cratesio.ui

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import io.github.andraantariksa.cratesio.R
import io.github.andraantariksa.cratesio.data.api.model.CrateSummary.CrateSummary
import io.github.andraantariksa.cratesio.utils.InjectorUtils
import kotlinx.android.synthetic.main.fragment_summary.*
import kotlinx.coroutines.launch


class SummaryFragment : ScopedFragment() {
//    private lateinit var viewModelFactory: CratesViewModelFactory
//    private lateinit var viewModel: CratesViewModel
    private val viewModel: CratesViewModel by activityViewModels {
        InjectorUtils.provideCratesViewModelFactory(requireContext())
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_summary, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

//        viewModelFactory = InjectorUtils.provideCratesViewModelFactory(context!!)
//        viewModel = ViewModelProvider(this, viewModelFactory)
//            .get(CratesViewModel::class.java)

        viewModel.cratesSummaryLast?.let {
            setupSummaryRecyclerView(it)
        }
        fetchRecyclerViewData()
    }

    private fun fetchRecyclerViewData() {
        launch {
            val crateSummaryLiveData = viewModel.crateSummary.await()
            crateSummaryLiveData.observe(viewLifecycleOwner, Observer {
                setupSummaryRecyclerView(it)
            })
        }
    }

    private fun setupSummaryRecyclerView(crateSummary: CrateSummary) {
        viewModel.cratesSummaryLast = crateSummary

        textViewCratesTotalNum.text = crateSummary.numCrates.toString()
        textViewDownloadsTotalNum.text = crateSummary.numDownloads.toString()

        val newCratesAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.newCrates)
        recyclerViewNewCrates.layoutManager = LinearLayoutManager(context)
        recyclerViewNewCrates.adapter = newCratesAdapter

        val mostDownloadedAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostDownloaded)
        recyclerViewMostDownloaded.layoutManager = LinearLayoutManager(context)
        recyclerViewMostDownloaded.adapter = mostDownloadedAdapter

        val justUpdatedAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.justUpdated)
        recyclerViewJustUpdated.layoutManager = LinearLayoutManager(context)
        recyclerViewJustUpdated.adapter = justUpdatedAdapter

        val mostRecentlyDownloaded =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerViewMostRecentlyDownloaded.layoutManager = LinearLayoutManager(context)
        recyclerViewMostRecentlyDownloaded.adapter = mostRecentlyDownloaded

        val mostPopularKeywords =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerViewPopularKeywords.layoutManager = LinearLayoutManager(context)
        recyclerViewPopularKeywords.adapter = mostPopularKeywords

        val popularCategories =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerPopularCategories.layoutManager = LinearLayoutManager(context)
        recyclerPopularCategories.adapter = popularCategories
    }
}

那么,是什么导致片段打开缓慢?我该如何解决?我使用共享视图模型的方法是否错误?

编辑

所以我必须以异步方式运行setupSummaryRecyclerView。但是还是比较慢

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        viewModelFactory = InjectorUtils.provideCratesViewModelFactory(context!!)
        viewModel = ViewModelProvider(this, viewModelFactory)
            .get(CratesViewModel::class.java)

        launch {
            viewModel.cratesSummaryLast?.let {
                setupSummaryRecyclerView(it)
            }
            fetchRecyclerViewData()
        }
    }

【问题讨论】:

  • "是什么导致片段打开缓慢?" -- 您需要分析您的代码,无论是使用 Android Studio 工具还是简单的Log 语句,以确定您将时间花在哪里。
  • @CommonsWare 谢谢,我才学了10分钟,自己找到答案了

标签: android kotlin android-fragments mvvm viewmodel


【解决方案1】:

好吧,原来我忘记以异步方式setupSummaryRecyclerView :) 。另外,by activityViewModels 看起来很慢,所以我也让它异步运行。

package io.github.andraantariksa.cratesio.ui

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import io.github.andraantariksa.cratesio.R
import io.github.andraantariksa.cratesio.data.api.model.CrateSummary.CrateSummary
import io.github.andraantariksa.cratesio.utils.InjectorUtils
import kotlinx.android.synthetic.main.fragment_summary.*
import kotlinx.coroutines.launch


class SummaryFragment : ScopedFragment() {
    private lateinit var viewModel: CratesViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_summary, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        launch {
            val viewModelLateInit by activityViewModels<CratesViewModel> {
                InjectorUtils.provideCratesViewModelFactory(requireContext())
            }
            viewModel = viewModelLateInit

            fetchRecyclerViewData()
        }
    }

    private fun fetchRecyclerViewData() {
        launch {
            viewModel.cratesSummaryLast?.let {
                setupSummaryRecyclerView(it, false)
            }

            val crateSummaryLiveData = viewModel.crateSummary.await()
            crateSummaryLiveData.observe(viewLifecycleOwner, Observer {
                setupSummaryRecyclerView(it)
            })
        }
    }

    private fun setupSummaryRecyclerView(crateSummary: CrateSummary, cache: Boolean = true) {
        if (cache) {
            viewModel.cratesSummaryLast = crateSummary
        }

        textViewCratesTotalNum.text = crateSummary.numCrates.toString()
        textViewDownloadsTotalNum.text = crateSummary.numDownloads.toString()

        val newCratesAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.newCrates)
        recyclerViewNewCrates.layoutManager = LinearLayoutManager(context)
        recyclerViewNewCrates.adapter = newCratesAdapter

        val mostDownloadedAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostDownloaded)
        recyclerViewMostDownloaded.layoutManager = LinearLayoutManager(context)
        recyclerViewMostDownloaded.adapter = mostDownloadedAdapter

        val justUpdatedAdapter =
            CrateSummaryRecyclerViewAdapter(crateSummary.justUpdated)
        recyclerViewJustUpdated.layoutManager = LinearLayoutManager(context)
        recyclerViewJustUpdated.adapter = justUpdatedAdapter

        val mostRecentlyDownloaded =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerViewMostRecentlyDownloaded.layoutManager = LinearLayoutManager(context)
        recyclerViewMostRecentlyDownloaded.adapter = mostRecentlyDownloaded

        val mostPopularKeywords =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerViewPopularKeywords.layoutManager = LinearLayoutManager(context)
        recyclerViewPopularKeywords.adapter = mostPopularKeywords

        val popularCategories =
            CrateSummaryRecyclerViewAdapter(crateSummary.mostRecentlyDownloaded)
        recyclerPopularCategories.layoutManager = LinearLayoutManager(context)
        recyclerPopularCategories.adapter = popularCategories
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-30
    • 2019-08-21
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 2020-05-15
    • 2018-06-22
    • 1970-01-01
    相关资源
    最近更新 更多