I have got a function displayDirectoryContents2(file: File) which scans all the file and check for files and directories. What I want is to display the current file path in a textview in UI thread
lateinit var textView: TextView
GlobalScope.launch(Dispatchers.IO) {
displayDirectoryContents2(file)
}
Code for the function
private fun displayDirectoryContents2(dir: File?){
try {
val files = dir?.listFiles()!!
files.forEach {
if (it.isDirectory) {
displayDirectoryContents2(it)
} else {
if (it.isFile) {
textView.text = it.name // to Update the file name in UI thread
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
I am new to Kotlin Coroutines. Actually I want to run function displayDirectoryContents2(file: File) in background thread and update the name of the file the function is reading in UI thread just like AsyncTask.
To specify the thread on which to run the action, construct the Handler using a Looper for the thread. A Looper is an object that runs the message loop for an associated thread. Once you've created a Handler , you can then use the post(Runnable) method to run a block of code in the corresponding thread.
Choosing between a service and a threadA service is simply a component that can run in the background, even when the user is not interacting with your application, so you should create a service only if that is what you need.
Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages. On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.
If you put long running work on the UI thread, you can get ANR errors. If you have multiple threads and put long running work on the non-UI threads, those non-UI threads can't inform the user of what is happening.
You can either switch dispatcher contexts (Dispatchers.IO for the logic, then to Dispatchers.Main for updating the UI), or you can move your code into a ViewModel and there use the same context switching technique or use postvalue() of LiveData. An example of doing the latter below. You can read on ViewModel here: https://developer.android.com/topic/libraries/architecture/viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MyViewModel() : ViewModel() {
private val files: MutableLiveData<List<String>> by lazy {
MutableLiveData<List<String>>()
}
fun loadFiles(path: String) {
viewModelScope.launch(){
doLoadFiles()
}
}
private suspend fun doLoadFiles() {
withContext(Dispatchers.IO) {
val results = listOf("patha", "pathb")//replace with your actual code
files.postValue(results)
}
}
fun getFiles(): LiveData<List<String>> = files
}
Then call it like this from your activity
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val model = ViewModelProviders.of(this)[MyViewModel::class.java]
model.getFiles().observe(this, Observer<List<String>>{ paths ->
// update UI
println (paths)
})
model.loadFiles("S")
}
In your build.gradle file, make sure to import the relevant dependencies
def lifecycle_ver = "2.2.0-rc02"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_ver"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_ver"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_ver"
You can make displayDirectoryContents2
suspended function and then use withContext
to switch context.
suspend fun displayDirectoryContents2() {
...
withContext(Dispatchers.Main) {
textView.text = it.name
}
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With