如何在科特林装载

时间:2020-01-27 18:15:51

标签: kotlin loading splash-screen

我的MainActivity包含一个可加载4个片段的ViewPager,每个片段应从服务器加载大量数据。

因此,当我的应用程序要首次运行时,几乎要花费3秒钟以上的时间(例如,如果您退出该应用程序但未从“最近的应用程序”窗口中清理它并重新打开它) )大约需要1秒。

在加载时会显示白屏。

除了显示白色屏幕之前,还有什么方法可以显示我自己的图像吗? 像启动页面一样的东西?

1 个答案:

答案 0 :(得分:1)

如果您在主线程上执行长时间运行的操作,则可能会遇到ANR crash的风险。

您每个片段的布局都应具有一个最初可见的加载视图以及您的数据视图。像这样:

不是代码

FrameLayout
    loading_view (can show a progress spinner or something, size is match parent)
    content_view (probably a RecyclerView, initial visibility=GONE, size is match parent)
/FrameLayout

您需要对后台线程或协程执行长时间运行的操作,然后在准备好在UI中显示数据时交换这两个视图的可见性。

由于Fragment是一个UI控制器,因此您不应直接处理Fragment代码中的数据加载。 Android Jetpack库为此提供了ViewModel类。您将像这样设置ViewModel。在此示例中,MyData可以是任何东西。在您的情况下,可能是列表或某物的集合。

class MyBigDataViewModel(application: Application): AndroidViewModel(application) {

    private val _myBigLiveData = MutableLiveData<MyData>()
    val myBigLiveData: LiveData<MyData>() = _myBigLiveData 

    init {
        loadMyBigData()
    }

    private fun loadMyBigData() {
        viewModelScope.launch { // start a coroutine in the main UI thread
            val myData: MyData = withContext(Dispatchers.Default) { 
                // code in this block is done on background coroutine
                // Calculate MyData here and return it from lambda
                // If you have a big for-loop, you might want to call yield()
                // inside the loop to allow this job to be cancelled early if
                // the Activity is closed before loading was finished.
                //...
                return@withContext calculatedData
            }

            // LiveData can only be accessed from the main UI thread so
            // we do it outside the withContext block
            _myBigLiveData.value = myData
        }
    }

}

然后在您的片段中,观察实时数据以在准备好UI时对其进行更新。下面使用fragment-ktx库,您需要将其添加到项目中。您绝对应该阅读documentation on ViewModel

class MyFragment: Fragment() {

    // ViewModels should not be instantiated directly, or they won't be scoped to the
    // UI life cycle correctly. The activityViewModels delegate handles instantiation for us.
    private val model: MyBigDataViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model.myBigLiveData.observe(this, Observer<MyData> { myData ->
            loading_view.visibility = View.GONE
            content_view.visibility = View.VISIBLE
            // use myData to update the view content
        })
    }
}