问题
I have an initialization block in onCreateView, where some variables are assigned from SharedPreferences, DB or Network (currently from SharedPreferences).
I want to update views with these values in onViewCreated. But they update with empty values before a coroutine in onCreateView finishes. How to wait until the coroutine finishes in main thread?
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    ...
    GlobalScope.launch(Dispatchers.Main) {
        val job = GlobalScope.launch(Dispatchers.IO) {
            val task = async(Dispatchers.IO) {
                settingsInteractor.getStationSearchCountry().let {
                    countryName = it.name
                }
                settingsInteractor.getStationSearchRegion().let {
                    regionName = it.name
                }
            }
            task.await()
        }
        job.join()
    }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    country.updateCaption(countryName)
    region.updateCaption(regionName)
}
UPDATE (20-05-2019)
Currently I don't use onViewCreated. I write code in onCreate and onCreateView. In onCreateView I access views this way: view.country.text = "abc" and so on.
回答1:
In your case you don't need to use GlobalScope as a coroutine context (you can but it is not recommended as per docs). You need a local scope:
private var job: Job = Job()
override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job
@Override
public void onDestroy() {
    super.onDestroy();
    job.cancel()
}
Also your fragment should implement CoroutineScope and to use Dispatchers.Main in Android add dependency to app's build.gradle:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
The code to wait until the coroutine finishes:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    launch {
        val operation = async(Dispatchers.IO) {
            settingsInteractor.getStationSearchCountry().let {
                countryName = it.name
            }
            settingsInteractor.getStationSearchRegion().let {
                regionName = it.name
            }
        }
        operation.await() // wait for result of I/O operation without blocking the main thread
        // update views
        country.updateCaption(countryName)
        region.updateCaption(regionName)
    }
}
回答2:
It's better to use async instead of launch https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html. 
Create lateinit val dataLoad: Deferred<Pair<String, String>. init it as dataLoad = GlobalScope.async(Dispatchers.Defailt) {} in onCreateView or earlier.
launch new coroutine in UI scope in onViewCreated. Wait for result in that coroutine val data = dataLoad.await() and then apply data to ui
来源:https://stackoverflow.com/questions/53665470/wait-until-kotlin-coroutine-finishes-in-oncreateview