Wednesday, March 14, 2018

android kotlin - AsyncTask with cancel progress example

MainActivity.kt

package com.cfsuman.kotlinexamples

import android.content.Context
import android.os.AsyncTask
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Initialize a new instance of AsyncImageDownload class
        val task = AsyncImageDownload(this,root_layout,progress_bar,text_view)


        // Button to start multiple images download
        button_start.setOnClickListener{
            task.execute(
                    "https://images.freeimages.com/images/large-previews/310/spring-1-1405906.jpg",
                    "https://images.freeimages.com/images/large-previews/8f3/white-flower-power-1403046.jpg",
                    "https://images.freeimages.com/images/large-previews/81c/flower-1393311.jpg",
                    "https://images.freeimages.com/images/large-previews/7f7/statice-1406388.jpg",
                    "https://images.freeimages.com/images/large-previews/760/wedding-flower-1188350.jpg"
            )

            it.isEnabled = false
            button_cancel.isEnabled = true
        }


        // Button to cancel the async task
        button_cancel.setOnClickListener{
            task.cancel(true)
            it.isEnabled = false
        }


        // Set a click listener for root layout
        root_layout.setOnClickListener{
            // Get the async task status and show it using toast message
            when(task.status){
                AsyncTask.Status.RUNNING -> toast("Task running")
                AsyncTask.Status.PENDING -> toast("Task pending")
                AsyncTask.Status.FINISHED -> toast("Task finished")
                else -> toast("Task status Unknown")
            }
        }
    }


    // Extension function to show toast message
    fun Context.toast(message:String){
        Toast.makeText(this,message,Toast.LENGTH_SHORT).show()
    }
}
AsyncDownloads.kt

package com.cfsuman.kotlinexamples

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.AsyncTask
import android.widget.*
import java.net.URL


class AsyncImageDownload(
        val context: Context,
        val rootLayout: LinearLayout,
        val progressBar: ProgressBar,
        val textView: TextView
    )
    : AsyncTask<String, Int, MutableList<Bitmap>>(){


    // Before async task start
    override fun onPreExecute() {
        progressBar.progress = 0
        textView.text = "Download started..."
        super.onPreExecute()
    }


    // Manage background async task
    override fun doInBackground(vararg  params: String): ArrayList<Bitmap>{
        val list = ArrayList<Bitmap>()

        // Loop through the task and execute them
        for( i in 0 until params.size){
            val urlOfImage = URL(params[i])
            try {
                val inputStream = urlOfImage.openStream()
                list.add(BitmapFactory.decodeStream(inputStream)!!)
            } catch (e: Exception) { // Catch the download exception
                e.printStackTrace()
            }

            // Publish the async task progress in percentage
            publishProgress(((i + 1) / params.size.toFloat() * 100).toInt())

            // If user cancel the task at runtime
            if(isCancelled)break
        }
        return list
    }


    // Display the async tas progress
    override fun onProgressUpdate(vararg values: Int?) {
        progressBar.progress = values[0]!!
        textView.text = "Download completed... ${values[0]}%"
        Toast.makeText(context,"Downloaded ${values[0]} %",Toast.LENGTH_LONG).show()
        super.onProgressUpdate(values[0])
    }


    // Manage completed task after user cancel async task
    override fun onCancelled(result: MutableList<Bitmap>?) {
        textView.text = "Task cancelled...\n ${result!!.size} files download success"

        for (bitmap in result){
            rootLayout.addView(newImageView(bitmap))
        }

        super.onCancelled(result)
    }


    // Manage result after completed async task
    override fun onPostExecute(result: MutableList<Bitmap>?) {
        textView.text = "Task finish...\n ${result?.size} files download success"
        for (bitmap in result!!){
            rootLayout.addView(newImageView(bitmap))
        }

        super.onPostExecute(result)
    }


    // Method to create a new ImageView instance
    private fun newImageView(bitmap: Bitmap): ImageView {
        val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 300)
        params.bottomMargin = 15
        val imageView = ImageView(context)
        imageView.layoutParams = params
        imageView.setImageBitmap(bitmap)
        imageView.setBackgroundColor(Color.LTGRAY)
        imageView.setPadding(10,10,10,10)
        return imageView
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#92a692"
    android:padding="16dp"
    >
    <LinearLayout
        android:id="@+id/root_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
        <Button
            android:id="@+id/button_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Downloads"
            />
        <Button
            android:id="@+id/button_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cancel Downloads"
            android:textColor="#ff0400"
            android:enabled="false"
            />
        <ProgressBar
            android:id="@+id/progress_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:indeterminate="false"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            />
        <TextView
            android:id="@+id/text_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:gravity="center"
            android:textStyle="bold"
            />
    </LinearLayout>
</ScrollView>
More android examples