AsyncTask in Android with Kotlin

前端 未结 10 1513
离开以前
离开以前 2020-12-13 12:31

How to make an API call in Android with Kotlin?

I have heard of Anko . But I want to use methods provided by Kotlin like in Android we have Asynctask for background

相关标签:
10条回答
  • 2020-12-13 13:07

    This is how I do in my projects to avoid memory leaks:

    I created an abstract base Async Task class for Async loading

    import android.os.AsyncTask
    
    abstract class BaseAsyncTask(private val listener: ProgressListener) : AsyncTask<Void, Void, String?>() {
    
        interface ProgressListener {
            // callback for start
            fun onStarted()
    
            // callback on success
            fun onCompleted()
    
            // callback on error
            fun onError(errorMessage: String?)
    
        }
    
        override fun onPreExecute() {
            listener.onStarted()
    
        }
    
        override fun onPostExecute(errorMessage: String?) {
            super.onPostExecute(errorMessage)
            if (null != errorMessage) {
                listener.onError(errorMessage)
            } else {
                listener.onCompleted()
            }
        }
    }
    

    USAGE:

    Now every time I have to perform some task in background, I create a new LoaderClass and extend it with my BaseAsyncTask class like this:

    class LoadMediaTask(listener: ProgressListener) : BaseAsyncTask(listener) {
    
        override fun doInBackground(vararg params: Void?): String? {
    
            return VideoMediaProvider().allVideos
        }
    }
    

    Now you can use your new AsyncLoader class any where in your app.

    Below is an example to Show/Hide progress bar & handle Error/ Success scenario:

       LoadMediaTask(object : BaseAsyncTask.ProgressListener {
                override fun onStarted() {
                    //Show Progrss Bar
                    loadingBar.visibility = View.VISIBLE
                }
    
                override fun onCompleted() {
                    // hide progress bar
                    loadingBar.visibility = View.GONE
                    // update UI on SUCCESS
                    setUpUI()
                }
    
                override fun onError(errorMessage: String?) {
                    // hide progress bar
                    loadingBar.visibility = View.GONE
                    // Update UI on ERROR
                    Toast.makeText(context, "No Videos Found", Toast.LENGTH_SHORT).show()
                }
    
            }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
    
    0 讨论(0)
  • 2020-12-13 13:07
      private fun updateUI(account: GoogleSignInAccount?) {
        if (account != null) {
            try {
                AsyncTaskExample().execute()
            } catch (e: Exception) {
            }
        }
    }
    inner class AsyncTaskExample : AsyncTask<String, String, String>() {
    
                override fun onPreExecute() {
                    super.onPreExecute()
    
                }
    
                override fun doInBackground(vararg p0: String?): String {
    
                    var Result: String = "";
                    try {
                        googleToken = GoogleAuthUtil.getToken(activity, accountVal, "oauth2:https://www.googleapis.com/auth/userinfo.profile")
                        signOut()
                    } catch (e: Exception) {
                        signOut()
                    }
    
    
                    signOut()
    
                    return Result
                }
    
                override fun onPostExecute(result: String?) {
                    super.onPostExecute(result)
                    socialPrsenter.setDataToHitApiGoogleLogin(googleToken ?: "")
    
                }
            }
    
    0 讨论(0)
  • 2020-12-13 13:10

    AsyncTask was deprecated in API level 30. To implement similar behavior we can use Kotlin concurrency utilities (coroutines).

    Create extension function on CoroutineScope:

    fun <R> CoroutineScope.executeAsyncTask(
            onPreExecute: () -> Unit,
            doInBackground: () -> R,
            onPostExecute: (R) -> Unit
    ) = launch {
        onPreExecute()
        val result = withContext(Dispatchers.IO) { // runs in background thread without blocking the Main Thread
            doInBackground()
        }
        onPostExecute(result)
    }
    

    Now it can be used on any CoroutineScope instance, for example, in ViewModel:

    class MyViewModel : ViewModel() {
    
          fun someFun() {
              viewModelScope.executeAsyncTask(onPreExecute = {
                  // ...
              }, doInBackground = {
                  // ...
                  "Result" // send data to "onPostExecute"
              }, onPostExecute = {
                  // ... here "it" is a data returned from "doInBackground"
              })
          }
      }
    

    or in Activity/Fragment:

    lifecycleScope.executeAsyncTask(onPreExecute = {
          // ...
      }, doInBackground = {
          // ...
          "Result" // send data to "onPostExecute"
      }, onPostExecute = {
          // ... here "it" is a data returned from "doInBackground"
      })
    

    To use viewModelScope or lifecycleScope add next line(s) to dependencies of the app's build.gradle file:

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
    
    0 讨论(0)
  • 2020-12-13 13:12

    I always use this form:

    open class LoadingProducts : AsyncTask<Void, Void, String>() {
    
    private var name = ""
    
        override fun doInBackground(vararg p0: Void?): String {
    
            for (i in 1..100000000) {
                if (i == 100000000) {
                    name = "Hello World"
                }
            }
            return name
        }
    }
    

    You invoke it in the following way:

    loadingProducts = object : LoadingProducts() {
            override fun onPostExecute(result: String?) {
                super.onPostExecute(result)
    
                Log.e("Result", result)
            }
        }
    
    loadingProducts.execute()
    

    I use the open so that I can call the onPostExecute method for the result.

    0 讨论(0)
提交回复
热议问题