Sunday, February 5, 2017

android - AsyncTask cancel example

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#e3eef5"
    >
    <Button
        android:id="@+id/btn_do"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Do AsyncTask"
        android:layout_margin="25dp"
        android:layout_gravity="top|start"
        />
    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        app:layout_anchor="@id/btn_do"
        app:layout_anchorGravity="right|center"
        android:layout_gravity="end|center"
        />
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_anchor="@id/btn_do"
        android:layout_gravity="bottom|center_horizontal"
        app:layout_anchorGravity="bottom|center_horizontal"
        android:textSize="20sp"
        android:gravity="center_horizontal"
        />
</android.support.design.widget.CoordinatorLayout>
MainActivity.java

package com.cfsuman.me.androidcodesnippets;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {
    private Context mContext;
    private Activity mActivity;

    private CoordinatorLayout mCLayout;
    private Button mButtonDo;
    private Button mButtonCancel;
    private TextView mTextView;

    private AsyncTask mMyTask;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get the application context
        mContext = getApplicationContext();
        mActivity = MainActivity.this;

        // Get the widget reference from XML layout
        mCLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
        mButtonDo = (Button) findViewById(R.id.btn_do);
        mButtonCancel = (Button) findViewById(R.id.btn_cancel);
        mTextView = (TextView) findViewById(R.id.tv);

        // Initialize a new click listener for positive button widget
        mButtonDo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Empty the TextView
                mTextView.setText("");
                // Execute the async task
                mMyTask = new DownloadTask()
                        .execute("Task 1","Task 2","Task 3","Task 4", "Task 5");
            }
        });

        // Click listener for cancel button
        mButtonCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                /*
                    cancel
                        boolean cancel (boolean mayInterruptIfRunning)
                            Attempts to cancel execution of this task. This attempt will fail if
                            the task has already completed, already been cancelled, or could not be
                            cancelled for some other reason. If successful, and this task has not
                            started when cancel is called, this task should never run. If the task
                            has already started, then the mayInterruptIfRunning parameter determines
                            whether the thread executing this task should be interrupted in an
                            attempt to stop the task.
                */
                mMyTask.cancel(true);
            }
        });
    }

    /*
        AsyncTask
            AsyncTask enables proper and easy use of the UI thread. This class allows you to perform
            background operations and publish results on the UI thread without having
            to manipulate threads and/or handlers.
    */
    private class DownloadTask extends AsyncTask<String,Integer,List<String>>{
        // Before the tasks execution
        protected void onPreExecute(){
            mTextView.setTextColor(Color.BLUE);
            mTextView.setText(mTextView.getText() + "\nStarting task....");
        }

        // Do the task in background/non UI thread
        protected List<String> doInBackground(String...tasks){
            // Get the number of task
            int count = tasks.length;
            // Initialize a new list
            List<String> taskList= new ArrayList<>(count);

            // Loop through the task
            for(int i =0;i<count;i++){
                // Do the current task task here
                String currentTask = tasks[i];
                taskList.add(currentTask);

                // Sleep the UI thread for 1 second
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // Publish the async task progress
                // Added 1, because index start from 0
                publishProgress((int) (((i+1) / (float) count) * 100));

                // If the AsyncTask cancelled
                if(isCancelled()){
                    break;
                }
            }
            // Return the task list for post execute
            return taskList;
        }

        /*
            onCancelled
                void onCancelled ()
                    Applications should preferably override onCancelled(Object). This method
                    is invoked by the default implementation of onCancelled(Object).

                    Runs on the UI thread after cancel(boolean) is invoked and
                    doInBackground(Object[]) has finished.
        */
        protected void onCancelled(){
            // Do something when async task is cancelled
            mTextView.setTextColor(Color.RED);
            mTextView.setText(mTextView.getText() + "\n\nOperation is cancel..." );
        }

        // After each task done
        protected void onProgressUpdate(Integer... progress){
            mTextView.setText(mTextView.getText() + "\nCompleted...." + progress[0] + "%");
        }

        // When all async task done
        protected void onPostExecute(List<String> result){
            mTextView.setText(mTextView.getText() + "\n\nDone....");
            for (int i=0;i<result.size();i++){
                mTextView.setText(mTextView.getText() + "\n" + result.get(i));
            }
        }
    }
}