Threading in Android

April 26, 2014

Source code

You can find the latest source code over at github: the source at github.

Introduction

Again another resume article about Android. This time I will cover threading. And in the accompaning sourcecode there is an application for Android allowing you to experiment with the various options available.

Not much assumptions are made on the knowledge required for understanding this article. A basic knowledge of Android programming and knowing the concept of a thread should suffice.

Background

Long running tasks on the UI thread

A usual Android application has only a single thread on which all work done by your application is executed. This thread is known as the UI thread. That also includes anything done in your eventhandlers and any updating of the user interface. The result of this is that if you are doing anything in an eventhandler that can take a long time to execute, the UI of your application will freeze/not be updated during this time. Whats even more, Android will show a dialog telling the user that the application is not responding!

buttonDoIt.setOnClickListener(
new Button.OnClickListener(){   
  @Override  public void onClick(View arg0) 
  {   
    LongRunningTask();
  }       
});

In which the method LongRunningTask looks like:

public void LongRunningTask()
{
  for(int i = 0; i < cnt; i++)
  {
    try {
      Thread.sleep(1000);
    } catch (Exception e) {
      Log.v("Error: ", e.toString());
    }
    // You will not see anything of this because
    //	this loop is blocking the updating of the UI
    //  so you will not see the textViews text being set
    textView.setText("Progress: " + i);
  }
}		

What you need to do is execute your long running task on another thread than the UI thread. For this you will need to create an Android thread.

Long running tasks on their own thread

To execute a long running task in another thread, you create a new thread and implement the long running code in the thread’s run() method. After this, you start the thread by calling it’s start() method.

However, there is a caveat here to. You cannot just update your UI from this other thread because of thread synchronization issues. Android enforces that updating the UI can only be done from a single thread: the UI thread. And therefore you must delegate the updating back to the UI thread. You do this by inserting a message into the messagequeue of the UI thread. I will explain this a bit further, but for now, here’s the code how you do this.

// This handler will be associated with the UI thread
Handler uiHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
    textView.setText("Progress: " + msg.what);			
  }
};

private void CreateThread() {
  Thread t = new Thread() {
    public void run() {
      for(int i = 0; i < cnt; i++)
      {
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
          Log.v("Error: ", e.toString());
        }
        if(feedBackByHandler)
        {
          // This is not allowed and will throw an exception.
          textView.setText("Progress: " + i);
        }
        else
        {
          // You can update the UI by sending messages to the UI thread
          uiHandler.sendMessage(uiHandler.obtainMessage(i));
        }
      }
    }
  };
  t.start();
}

Long running tasks on their own thread using AsyncTask

In the above item you had to write a lot of boilerplate code for doing something as simple as performing a long running task and informing the UI of the progress made. Fortunately, their is a simpler way: you can create your own class derived from AsyncTask.

The AsyncTask class provides 4 methods you can override

  • doInBackground: here you do the actual work. This method cannot access any UI controls and is executed on a seperate thread.
  • onProgressUpdate: called when publishing progress updates by calling publishProgress in doInBackground. You can directly access any UI controls in this method because it is executed on the UI thread.
  • onPreExecute: called just before calling doInBackground. You can directly access any UI controls in this method because it is executed on the UI thread.
  • onPostExecute: called just after calling doInBackground. You can directly access any UI controls in this method because it is executed on the UI thread.

What this does is execute your work on a separate thread, but handle all the messageing needed to update your UI on the UI thread. As a result the code becomes:

class LongRunningAsyncTask extends AsyncTask<String, Integer, Integer> {
  @Override
   protected Integer doInBackground(String... dummy) {
    int i = 0;
    for(; i < cnt; i++)
    {
      try {
        Thread.sleep(1000);
      } catch (Exception e) {
        Log.v("Error: ", e.toString());
      }
      // By publishing your progress, Android calls the onProgressUdate method  
      //	with the value provided
      publishProgress(i);
    }
    
    return i;
   }

  @Override
   protected void onProgressUpdate(Integer... progress) {
     textView.setText("Progress: " + progress[0]);
   }

  @Override
   protected void onPreExecute() {
     textView.setText("Started!");
   }

  @Override
   protected void onPostExecute(Integer result) {
     textView.setText("Finished with " + result + "!");
   }
}
   
@Override
public void onCreate(Bundle savedInstanceState) {
  
   Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
   buttonDoIt.setOnClickListener(
    new Button.OnClickListener(){   
      @Override  public void onClick(View arg0) 
      {   
        new LongRunningAsyncTask().execute("");
      }       
    });
     
}

Threads, Loopers and Handlers

You will surely have an idea of what a thread is, but what is a handler and a looper?

A handler is the Android way of making it possible to handle custom messages in the messageloop of a thread. Okay, what does this mean?

As you allready know, a thread is a flow of execution in your application and it can only do one single thing at a time. If you provide it an implementation of the run() method, it will execute this method and when the method is finished the thread will end its execution and be no longer available.

In code you would have something like this:

Thread t = new Thread() {
  public void run() {
    // whatever you do here, when your 
    //	code gets at the end of this method
    //	the thread will be finished
  }
};
t.start();

You can imagine that you would like a thread which is always available to you to do some stuff. You could create a queue in which you insert messages and those message tell the thread what to do. In the thread you write a loop which continuously checks this queue for messages and if you find one you execute the corresponding work. This is called “the messageloop”.

In code you would have something like this:

Thread t = new Thread() {
  public void run() {
    for(;;)
    {
      // we are effectively in an infinite loop,
      //	so this thread will never stop
      // Check if we have anything to do
      if(messageQueue.size() != 0)
      {
        // do whatever is in the messagequeue
      }
    }
  }
};
t.start();

Threads you create yourself have no such messageloop by default but the UI thread does. This messageloop is used to process the messages send by the Android operating system to your application. If you click a button, this results in a message pushed on the messagequeue, and the messageloop pulls it from this queue and handles it by calling your onClick event handler. While it is executing your onClick handler it can not do anything else. The creation of the queue and the managing of messages in the queue is done by a Looper object. If you want to put your own custom messages in the queue to be processed by this thread you need a Handler object: if the Looper sees your custom message in the messagequeue it will call the Handler of the thread and hand it your message. In the handleMessage of your custom Handler you then process this message.

Resuming we have the following:

  • Thread: a thread is a flow of execution in your program
  • Looper: a looper implements a for loop and a queue into which messages can be posted. Inside the for-loop it checks for messages in the queue.
  • Handler: a handler is called by a looper to process the messages in the queue. The handler must know what to do by the id of the message.
  • Message: a message identifies some work to perform. You create messages by calling any of the obtainMessage methods of the handler.

A Thread can have only a single Looper and a single Handler associated with it. So if you create a Looper or a Handler in a thread, Android will check if one exists allready and if so will hand you the existing one, and if not it will create a new object for you and automatically associate the looper or handler with the thread on which you created the object.

Long running tasks using Handlers: Blocking the UI thread

So, the UI Thread allready has a Looper associated with it implementing the default application messageloop. If you supply it a handler, then this will get used by the messageloop.

Because a thread can only do a single thing at a time, if you execute a long running operation in your handler, the messageloop can not handle any other messages, like subsequent clicking of for example a checkbox.

// This handler will be associated with the UI thread, hence this long running 
//	operation will prevent the ui thread of processing any other messages posted
//	to its messagequeue
Handler uiHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
    for(int i = 0; i < cnt; i++)
    {
      try {
        Thread.sleep(1000);
      } catch (Exception e) {
        Log.v("Error: ", e.toString());
      }
    }
    
    textView.setText(textView.getText()+"Did you succeed?");			
  }
};	
   
@Override
public void onCreate(Bundle savedInstanceState) {
  
  Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
  buttonDoIt.setOnClickListener(
      new Button.OnClickListener(){   
        @Override  public void onClick(View arg0) 
        {   
          // Send a custom message to the UI thread
          // This will start the long running operation on the UI thread
          uiHandler.sendMessage(uiHandler.obtainMessage()); 
        }       
      });
}

Long running tasks using Handlers: Not blocking the UI thread

To have a handler that does not block the UI thread, you must associate it with a different thread, thus you must create a new thread then associate a new looper with it and finally a handler. And it is to this handler you must send your message.

public class HandlerNonBlockingHandlerActivity extends Activity {
  
  Handler threadHandler = null;
  
  // This handler is created on the UI thread en thus associated with that thread
  //	this means that any code executed by this handler is executed on the UI thread
  Handler uiHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      textView.setText(textView.getText()+"Did you succeed?");			
    }
  };
    
  private void CreateThread() {
  
    // We create a new thread
    Thread t = new Thread() {
      public void run() {
        
        Looper.prepare();
        
        // In this thread we create a handler which is associated with this thread
        //	thus, everything executed by this handler is executed on this seperate thread
        //	and as a result, we are not blocking the UI thread
        threadHandler = new Handler() {
          @Override
          public void handleMessage(Message msg) {
            for(int i = 0; i < cnt; i++)
            {
              try {
                Thread.sleep(1000);
              } catch (Exception e) {
                Log.v("Error: ", e.toString());
              }
            }
            uiHandler.sendMessage(uiHandler.obtainMessage()); 		
          }
        };
        
        Looper.loop();

      }
    };
    t.start();
  }
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    
        Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
        buttonDoIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {   
                threadHandler.sendMessage(threadHandler.obtainMessage()); 
              }       
          });
        
        CreateThread();
  }
}

Do try this at home: the code

The code has seven activities demonstrating the concepts explained above.

When you startup the application you see following screen:

Each entry in the list demonstates a concept and provides controls to experiment.

Action On UIThread: LongRunningTaskOnUIThread

This sample demonstrates what you should not do: call the long running method in the onClick handler.

public class LongRunningTaskOnUIThread extends Activity {
     
  public void LongRunningTask()
  {
    for(int i = 0; i < cnt; i++)
    {
      try {
        Thread.sleep(1000);
      } catch (Exception e) {
        Log.v("Error: ", e.toString());
      }
      // You will not see anything of this because
      //	this loop is blocking the updating of the UI
      //  so you will not see the textViews text being set
      textView.setText("Progress: " + i);
    }
  }
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.text_view);
      textView=(TextView)findViewById(R.id.textView);		
      editTextTaskDuration=(EditText)findViewById(R.id.editTextTaskDuration);
      editTextTaskDuration.setText("" + cnt);
      
      Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
      buttonDoIt.setOnClickListener(
         new Button.OnClickListener(){   
           @Override  public void onClick(View arg0) 
           {   
            String taskDurationAsString = editTextTaskDuration.getText().toString();
            cnt = Integer.parseInt(taskDurationAsString);
             LongRunningTask();
           }       
       });
           
  }
  
  private TextView textView;	
  private EditText editTextTaskDuration;
  private int cnt = 5;

}

Running the sample shows the following screen:

If you push the button there are three things to notice:

  1. Allthough the code updates a textbox inside the loop, when running the program the text in the textbox does not get updated untill after about 5 seconds (or whatever task duration you filled in in the edit box): the time it takes to finish the loop.
  2. When clicking the checkbox during the first 5 seconds after pressing the button, the checkbox does not alter its state.
  3. If you set the task duration to a high value (20 did it for me), you’ll get an exception. That is because Android notices you are blocking the UI thread.

These two different things happening have a common cause: your loop is executed on the UI thread and therefore prohibits any processing of other events.

Action On Thread: LongRunningTaskOnOwnThread

This activity demonstrates executing a long running operation on another thread and giving feedback about progesssion in the UI

public class LongRunningTaskOnOwnThread extends Activity {
  
  // This handler will be associated with the UI thread
  Handler uiHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      textView.setText("Progress: " + msg.what);			
    }
  };
    
  private void CreateThread() {
    Thread t = new Thread() {
      public void run() {
        for(int i = 0; i < cnt; i++)
        {
          try {
            Thread.sleep(1000);
          } catch (Exception e) {
            Log.v("Error: ", e.toString());
          }
          if(feedBackByHandler)
          {
            // This is not allowed and will throw an exception.
            textView.setText("Progress: " + i);
          }
          else
          {
            // You can update the UI by sending messages to the UI thread
            uiHandler.sendMessage(uiHandler.obtainMessage(i));
          }
        }
      }
    };
    t.start();
  }
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.text_view_withcheckbox);
    textView=(TextView)findViewById(R.id.textView);
    chkOnHandler = (CheckBox)findViewById(R.id.checkBoxConfig);
    editTextTaskDuration=(EditText)findViewById(R.id.editTextTaskDuration);
    editTextTaskDuration.setText("" + cnt);
    
        Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
        buttonDoIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {       				
                feedBackByHandler = chkOnHandler.isChecked();
                String taskDurationAsString = editTextTaskDuration.getText().toString();
                cnt = Integer.parseInt(taskDurationAsString);
                CreateThread();
              }       
          });
              
  }
  
  private TextView textView;
  private CheckBox chkOnHandler;
  private EditText editTextTaskDuration;
  private int cnt = 5;
  private boolean feedBackByHandler = true;

}

Running the sample shows the following screen:

The checkbox “Update on custom thread” allows to select on which thread the UI should be updated, the UI thread being the only correct one of course. So if you check the option the application will crash, what is to be expected.

Running this code you wil notice two things, the opposite of what happened above:

  1. If you selecte the correct update option (see above), you will notice you receive the correct feedback in the UI.
  2. If you try to check the bottom checkbox you will succeed.

By executing your long running operation on a different thread you are no longer blocking the UI thread, thus allowing the UI to respond to other events.

Action with Async: LongRunningTaskWithAsyncTask

In the previous activity we had to write a lot of boiler plate code. This activity does exactly the same but uses an AsyncTask object, which provides feedback automatically on the UI thread

public class LongRunningTaskWithAsyncTask extends Activity {

  class LongRunningAsyncTask extends AsyncTask<String, Integer, Integer> {
    @Override
       protected Integer doInBackground(String... dummy) {
      int i = 0;
      for(; i < cnt; i++)
      {
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
          Log.v("Error: ", e.toString());
        }
        // By publishing your progress, Android calls the onProgressUdate method  
        //	with the value provided
        publishProgress(i);
      }
      
      return i;
       }

    @Override
       protected void onProgressUpdate(Integer... progress) {
         textView.setText("Progress: " + progress[0]);
       }

    @Override
       protected void onPreExecute() {
         textView.setText("Started!");
       }

    @Override
       protected void onPostExecute(Integer result) {
         textView.setText("Finished with " + result + "!");
       }
  }
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.text_view);
    textView=(TextView)findViewById(R.id.textView);
    editTextTaskDuration=(EditText)findViewById(R.id.editTextTaskDuration);
    editTextTaskDuration.setText("" + cnt);
    
       Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
       buttonDoIt.setOnClickListener(
         new Button.OnClickListener(){   
           @Override  public void onClick(View arg0) 
           {   
               String taskDurationAsString = editTextTaskDuration.getText().toString();
            cnt = Integer.parseInt(taskDurationAsString);
             new LongRunningAsyncTask().execute("");
           }       
       });
           
  }
  
  private TextView textView;
  private EditText editTextTaskDuration;
  private int cnt = 5;
}

Running the sample shows the following screen:

Blocking Action: HandlerBlockingHandlerActivity

This demonstrates the fact that a handler is associated with the thread on which it is created. It also demonstrates that simply the fact of creating a handler is not sufficient to make sure your long running operations aren’t blocking the UI !

In this case the handler is created on the UI thread, thus the long running operation is executed on the UI thread again blocking any updates of the UI

public class HandlerBlockingHandlerActivity extends Activity {
  
  // This handler will be associated with the UI thread, hence this long running 
  //	operation will prevent the ui thread of processing any other messages posted
  //	to its messagequeue
  Handler uiHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      for(int i = 0; i < cnt; i++)
      {
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
          Log.v("Error: ", e.toString());
        }
      }
      
      textView.setText(textView.getText()+"Did you succeed?");			
    }
  };	
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.text_view);
    textView=(TextView)findViewById(R.id.textView);
    editTextTaskDuration=(EditText)findViewById(R.id.editTextTaskDuration);
    editTextTaskDuration.setText("" + cnt);
    
        Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
        buttonDoIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {   
                   String taskDurationAsString = editTextTaskDuration.getText().toString();
                cnt = Integer.parseInt(taskDurationAsString);
                
            // Send a custom message to the UI thread
            // This will start the long running operation on the UI thread
                uiHandler.sendMessage(uiHandler.obtainMessage()); 
              }       
          });
  }
  
  private TextView textView;
  private EditText editTextTaskDuration;
  private int cnt = 5;
  
}

Running the sample shows the following screen:

Again you have the same two controls: a textbox in which we’d like to show the progress and a checkbox for you to check

In this case none of the above will succeed because the handler was created on the UI thread

NonBlocking Action: HandlerNonBlockingHandlerActivity

This is the counterpart of the above:

Here, first a Thread is created and inside it a Looper to have a message queue. Then a Handler is created which is associated to the created thread.

public class HandlerNonBlockingHandlerActivity extends Activity {
  
  Handler threadHandler = null;
  
  // This handler is created on the UI thread en thus associated with that thread
  //	this means that any code executed by this handler is executed on the UI thread
  Handler uiHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      textView.setText(textView.getText()+"Did you succeed?");			
    }
  };
    
  private void CreateThread() {
  
    // We create a new thread
    Thread t = new Thread() {
      public void run() {
        
        Looper.prepare();
        
        // In this thread we create a handler which is associated with this thread
        //	thus, everything executed by this handler is executed on this seperate thread
        //	and as a result, we are not blocking the UI thread
        threadHandler = new Handler() {
          @Override
          public void handleMessage(Message msg) {
            for(int i = 0; i < cnt; i++)
            {
              try {
                Thread.sleep(1000);
              } catch (Exception e) {
                Log.v("Error: ", e.toString());
              }
            }
            uiHandler.sendMessage(uiHandler.obtainMessage()); 		
          }
        };
        
        Looper.loop();

      }
    };
    t.start();
  }
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.text_view);
    textView=(TextView)findViewById(R.id.textView);
    editTextTaskDuration=(EditText)findViewById(R.id.editTextTaskDuration);
    editTextTaskDuration.setText("" + cnt);
    
        Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
        buttonDoIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {   
                
                   String taskDurationAsString = editTextTaskDuration.getText().toString();
                cnt = Integer.parseInt(taskDurationAsString);
                
                threadHandler.sendMessage(threadHandler.obtainMessage()); 
              }       
          });
        
        CreateThread();
  }
  
  private TextView textView;
  private EditText editTextTaskDuration;
  private int cnt = 5;
}

Deepdive into Handler: DeepDiveHandler

Now, let us dive a little deeper into what a Handler is actually capable of and how to send Messages.

public class DeepDiveHandler extends Activity {
  
  static final int MessageFromHandler = 0;
  static final int MessageAfterLooper = 1;

  static final int MessageShowText = 0;
  static final int MessageQuitLooper = 1;
  
  Handler threadHandler = null;
  Handler uiHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      switch (msg.what)
      {
      case MessageFromHandler:
        long uptimeSec = SystemClock.uptimeMillis() / 1000;
        long minutes = uptimeSec / 60;
        uptimeSec = uptimeSec % 60;
        
        textView.setText("Message=" + minutes + ":" + uptimeSec);			
        break;
      case MessageAfterLooper:
        textView.setText("After Looper.Loop()");			
      }
    }
  };
    
  private void CreateThread() {
    Thread t = new Thread() {
      public void run() {
        
        Looper.prepare();
        
        threadHandler = new Handler() {
          @Override
          public void handleMessage(Message msg) {
            switch (msg.what)
            {
            case MessageShowText:
              Message uiMsg = uiHandler.obtainMessage();
              uiMsg.what = MessageFromHandler;
              uiHandler.sendMessage(uiMsg); 		
              break;
            case MessageQuitLooper:
              this.getLooper().quit(); 		
              break;
            }
          }
        };
        
        // you will not get past here until you call the looper's quit() method
        Looper.loop();
        
        // this code only gets executed when the looper is stopped by calling it's quit() method
        Message uiMsg = uiHandler.obtainMessage();
        uiMsg.what = MessageAfterLooper;
        uiHandler.sendMessage(uiMsg); 		

      }
    };
    t.start();
  }
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.deepdivehandler_view);
    textView=(TextView)findViewById(R.id.textView);
    
        Button buttonStartIt = (Button)findViewById(R.id.buttonStartIt);       
        buttonStartIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {   
                CreateThread();
              }       
          });
        
        Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
        buttonDoIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {   
                Message showMsg = threadHandler.obtainMessage();
                showMsg.what = MessageShowText;
                threadHandler.sendMessage(showMsg); 
              }       
          });
        
        Button buttonStopIt = (Button)findViewById(R.id.buttonStopIt);       
        buttonStopIt.setOnClickListener(
            new Button.OnClickListener(){   
              @Override  public void onClick(View arg0) 
              {   
                Message quitLooperMsg = threadHandler.obtainMessage();
                quitLooperMsg.what = MessageQuitLooper;
                threadHandler.sendMessage(quitLooperMsg); 
              }       
          });

  }
  
  private TextView textView;

}

In the sample screen you have 3 buttons:

  1. Start thread: This button creates a new thread with an associated Looper and Handler
  2. Take action: This button sends messages to the Handler created by the “Start thread” button
  3. Stop thread: This button also sends a message to the Handler created by the “Start thread” button, but with a different payload then the “Take action” button, resulting in the thread to stop running.

Ok, what is happening here?

The “Take action” button sends a message to the Handler with a what-parameter of MessageShowText. This results in the Handler sending a message to the UI handler which then updates the text in the TextView

The “Stop thread” button sends a message to the Handler with a what-parameter of MessageQuitLooper. This results in a call of the Looper‘s quit()-method thus ending the looper and executing any code after the Looper‘s loop()-method call.

Deepdive into Async: DeepDiveAsync

Next, we’ll dive a little deeper in the funcitonality of AsyncTask

public class DeepDiveAsync extends Activity {
  
  class DeepDiveAsyncTask extends AsyncTask<String, Integer, Integer> {
    @Override
       protected Integer doInBackground(String... dummy) {
      int i = 0;
      try {
        for(; i < m_duration; i++)
        {
          Thread.sleep(1000);
          // if you do not check for cancellation you will not be able to 
          //	cancel your task using cancel(false)
          if(m_checkForCancellation) {
            if(isCancelled()) {
              // Just checking for cancellation isn't enough.
              // If you do not somehow return here prematurely
              //	your task will not be cancelled
              return i;
            }
          }
          
          // By publishing our progress, android will call the 
          //	onProgressUpdate method with the argument given here
          publishProgress(i);
        }
      } catch (Exception e) {
        Log.v("Error: ", e.toString());
      }
      
      // The value we return here will be forwarded to the
      //	onPostExecute method
      return i;
       }

    @Override
       protected void onProgressUpdate(Integer... progress) {
         textView.setText("Progress: " + progress[0]);
       }

    @Override
       protected void onPreExecute() {
         textView.setText("Started!");
       }

    @Override
       protected void onPostExecute(Integer result) {
         textView.setText("Finished with " + result + "!");
       }
    
    @Override
    protected void onCancelled() {
         textView.setText("Cancelled!");
    };
    
    public int getDuration()
    {
      return m_duration;
    }
    
    public void setDuration(int duration)
    {
      m_duration = duration;
    }
    
    public boolean getCheckForCancellation()
    {
      return m_checkForCancellation;
    }
    
    public void setCheckForCancellation(boolean checkForCancellation)
    {
      m_checkForCancellation = checkForCancellation;
    }
    
    private int m_duration = 5;
    private boolean m_checkForCancellation = false;
  }
     
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.deepdiveasync_view);
    textView=(TextView)findViewById(R.id.textView);
    editTextTaskDuration=(EditText)findViewById(R.id.editTextTaskDuration);
    checkBoxCheckForCancelation=(CheckBox)findViewById(R.id.checkBoxCheckForCancelation);
    
    deepDiveAsyncTask = new DeepDiveAsyncTask();
    
    editTextTaskDuration.setText(Integer.toString(deepDiveAsyncTask.getDuration()));  
    checkBoxCheckForCancelation.setChecked(deepDiveAsyncTask.getCheckForCancellation());
    
    
      Button buttonDoIt = (Button)findViewById(R.id.buttonDoIt);       
      buttonDoIt.setOnClickListener(
      new Button.OnClickListener(){   
        @Override  public void onClick(View arg0) 
        {   
          String taskDurationAsString = editTextTaskDuration.getText().toString();
          int taskDuration = Integer.parseInt(taskDurationAsString);
          deepDiveAsyncTask.setDuration(taskDuration);
          deepDiveAsyncTask.setCheckForCancellation(checkBoxCheckForCancelation.isChecked());
          deepDiveAsyncTask.execute("");
        }       
      });
      
      Button buttonCancelItWithInterrupt = (Button)findViewById(R.id.buttonCancelItWithInterrupt);       
      buttonCancelItWithInterrupt.setOnClickListener(
      new Button.OnClickListener(){   
        @Override  public void onClick(View arg0) 
        {   
          deepDiveAsyncTask.cancel(true);
        }       
      });
      
      Button buttonCancelItNoInterrupt = (Button)findViewById(R.id.buttonCancelItNoInterrupt);       
      buttonCancelItNoInterrupt.setOnClickListener(
      new Button.OnClickListener(){   
        @Override  public void onClick(View arg0) 
        {   
          deepDiveAsyncTask.cancel(false);
        }       
      });
        
  }
  
  private TextView textView;
  private EditText editTextTaskDuration;
  private CheckBox checkBoxCheckForCancelation;
  
  private DeepDiveAsyncTask deepDiveAsyncTask;
}

In the sample application we have 3 buttons:

  1. Take action: This button creates the AsyncTask using the parameters provided in the Task duration EditText and the Check for cancelation CheckBox
  2. Cancel action with interrupt: This button calls the AsyncTask‘s cancel(boolean mayInterruptIfRunning) with a parameter with value true allowing Android to interrupt the thread running the task.
  3. Cancel action no interrupt: This button calls the AsyncTask‘s cancel(boolean mayInterruptIfRunning) with a parameter with value false not allowing Android to interrupt the thread running the task.

What is happening?

The “Cancel action with interrupt” button calls the AsyncTask‘s cancel-method with a parameter of value true. This way we let Android interrupt the action immediately which we can see when pressing this button: the method onCancelled() of the AsyncTask is called immediately showing the message “Cancelled!”

The “Cancel action no interrupt” button calls the exact same method but with a parameter of value false. The result of this is that if you now call the method isCancelled() in your doInBackground method implementation it will return true and YOU can end the method. Read that sentence again: yes YOU are responsible for calling the isCancelled() method and taking the necessary steps to stop the execution. In the provided test application the checkbox “Check for cancelation” allows you to bypass this check. If you do that you will notice that your task is NOT cancelled.

Drawing in Android

November 28, 2012

Source code

You can find the latest source code over at github: the source at github.

Introduction

In my previous post I tried to provide a kind of one stop shop for things about multi touch on the Android platform. My initial intention was to do the same for drawing in 2D.

However, while documenting myself I quickly came to the conclusion that this subject is big. So I have reset my target. My main concern was with how to define shapes in XML resources, draw shapes and then to apply some transformations on these objects.

And that is what I will cover in this post: define drawing objects in XML resources and then apply transformations, like roating, scaling, etc… on them.

So, without aby further ado:

Background

Drawing from XML resources

Drawing from XML resources requires 3 steps:

  1. Define the resource in XML
  2. Load the resource
  3. Draw the resource on the screen

Step 1: Defining the shape as a resource

You define the resource in the resource directory of your project. You will notice you have several resource folders:

  • drawable
  • drawable-ldpi
  • drawable-mdpi
  • drawable-hdpi

This allows you to specify specific resources according to the screen resolution of the targetted Android device. The important word in previous sentence is “resolution”. Mind that this is not the same as screensize! Stackoverflow has a very nice postabout this.

Defining the shape in the xml goes like this:

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <stroke android:width="2px" android:color="#ffffff" />
    <solid android:color="#ffffd300"/>
</shape>

Step 2: Loading a resource as a shape

Resources res = context.getResources();
try {
	rectangleDrawable = (Drawable) res.getDrawable(R.drawable.rectangle_drawable);
} catch (Exception ex) {
	Log.e("Error", "Exception loading drawable: " + ex.getMessage());
}

In the above code, the context variable is the context as given in the constructor of your view class, or if you are loading the resources inside your activity, then you can use the this variable

rectangle_drawable is the name of the xml file created in Step 1

Step 3: Drawing the shapes

protected void onDraw(Canvas canvas) {
	rectangleDrawable.setBounds(x, y, x + width, y + height);
	rectangleDrawable.draw(canvas);
}

Drawing shapes is simple: you set the size of the shape and call the draw method of the Drawable class providing it the canvas on wich to draw.

Draw shapes created in code

Drawing shapes in code requires 2 steps:

  1. Create the shape in code
  2. Draw the shape

Step 1: Create the shape in code

rectangleDrawable = new ShapeDrawable(new RectShape());
ovalDrawable = new ShapeDrawable(new OvalShape());
arcDrawable = new ShapeDrawable(new ArcShape(45, 300));

Creating shapes in code is not at all difficult, but if you’re used to creating shapes in XML you might be in for a surprise: allthough you may think that providing a shape specific class to the constructor of the ShapeDrawable is similar as defining the shape of the drawable, this is NOT the same as choosing the shape to draw in the XML file. The class of the shapes created by defining them in XML is GradientDrawable and NOT ShapeDrawable.

Step 2: Drawing the shape

arcDrawable.getPaint().setColor(0xff74AC23);
arcDrawable.setBounds(x, y, x + width, y + height);
arcDrawable.draw(canvas);

Drawing the shapes is the same is when drawing shapes created from resources.

Applying transformations: using the Matrix class

I will not explain the basics of transformations and how matrix algebra fits in. There are enough references on the internet explaining this.

Using the matrix class,you can chain several types of tranformations together. The four supported types which you can apply are:

  1. Translation
  2. Rotation
  3. Scaling
  4. Skew

Each of these transformations has 3 methods in the Matrix class:

  1. A method to apply the transformation in front of all current transformations of the Matrix. This method starts with pre followed by the name of the tranformationtype
  2. A method to apply the transformation in the end of all current transformations of the Matrix. This method starts with post followed by the name of the tranformationtype
  3. A method to apply the tranformation instead of all current transformations of the Matrix. This method starts with set followed by the name of the tranformationtype

An important remark: a transformation is always made with repect to a point (except for a translation). This point is the origin of the drawing canvas, and in Android this point is at the upper left corner of the screen.

Translation

A translation in the xy-plane is defined by movement along the x-axis and along the y-axis.

A translation is done by any of the methods preTranslate, postTranslate and setTranslate

Rotation

A rotation in the xy-plane is defined by an angle expressed in degrees. The rotation is around the origin of the screen which is, as allready mentioned above, at the upper left corner of the screen.

Scaling

A scaling in the xy-plane, which in the case of Android is anisotropic, is defined by a scaling along the x-axis and a scaling along the y-axis. The scaling is again with respect to the origin of the screen, thus the upper left corner. As a result also the distance of the object you draw on the screen is multiplied by the scaling factor.

Skew

A skew, or in mathematics known as shear in the xy plane is also defined by two variables: kx and ky.

Applying transformations

Applying transformations in code is done as follows:

//create a matrix
Matrix matrix;
matrix = new Matrix();

//apply the transformations
//notice that by using the preScale method, the
//scaling will be applied before the translation
matrix.postTranslate(dx, dy);
matrix.preScale(sx, sy);

//concatenate the transformation to any 
//transformations allready applied to the canvas
canvas.concat(matrix);

//do your thing
rectangleDrawable.draw(canvas);

Applying transformations: using the Camera class

While the Matrix class allows you to define simple tranformations, the Camera class allows you to define transformations as they would happen when looking at the drawing plane from a certain point of view in space.

As such, it defines methods allowing you to position the camera in space:

  1. rotationX: rotation around the X-axis
  2. rotationY: rotation around the Y-axis
  3. rotationZ: rotation around the Z-axis
  4. translate: movement along the X, Y and Z-axis.

Rotation around the main axises

Rotations around the X-axis and Y-axis result in a type of deformation of the object you are transforming which can not be reproduced by a transformation defined by using a Matrix transformation. A rotation around the Z-axis is comparable with a regular rotation as defined by a Matrix tranformation.

Translation along the main axises

Translation along the X and Y axis corresponds to a regular translation using a Matrix transformation. A translation along the Z-axis can be seen as a scaling using a regular Matrix tranformation.

Applying transformations

Applying transformations in code is done as follows:

//create a camera
Camera camera;
camera = new Camera();

//apply the desired transformations
camera.rotateX(rotationX);

//get the transformation matrix
Matrix cameraMatrix = new Matrix();
camera.getMatrix(cameraMatrix);

//concatenate the transformation to any 
//transformations allready applied to the canvas
canvas.concat(matrix);

//do your thing
rectangleDrawable.draw(canvas);

Do try this at home: the code

The code has four views allowing you to experiment with what has been explained above. When you start the application you will see the following screen:

Each entry corresponds with a view allowing you to experiment with that feature. Following is an explanation of what entry corresponds with what view/java file and the configurations possible in that view:

Drawable in XML: CustomDrawableFromXMLView

public CustomDrawableFromXMLView(Context context) {
	super(context);

	Resources res = context.getResources();
	try {
		rectangleDrawable = (Drawable) res.getDrawable(R.drawable.rectangle_drawable);
		ovalDrawable = (Drawable) res.getDrawable(R.drawable.oval_drawable);
		lineDrawable = (Drawable) res.getDrawable(R.drawable.line_drawable);
		ringDrawable = (Drawable) res.getDrawable(R.drawable.ring_drawable);
	} catch (Exception ex) {
	   Log.e("Error", "Exception loading drawable: " + ex.getMessage());
	}

}

protected void onDraw(Canvas canvas) {
	if(fSetBounds)
	{
		rectangleDrawable.setBounds(x, y, x + width, y + height);
		ovalDrawable.setBounds(x, y, x + width, y + height);
		lineDrawable.setBounds(x, y, x + width, y + height);
		ringDrawable.setBounds(x, y, x + width, y + height);
	}
	if(fDrawRectangle)
		if(fCastToShapeDrawable)
			((ShapeDrawable)rectangleDrawable).draw(canvas);
		else if(fCastToGradientDrawable)
			((GradientDrawable)rectangleDrawable).draw(canvas);
		else
			rectangleDrawable.draw(canvas);
	if(fDrawOval)
		ovalDrawable.draw(canvas);
	if(fDrawLine)
		lineDrawable.draw(canvas);
	if(fDrawRing)
		ringDrawable.draw(canvas);
}

As is the intention of these posts, some variables allow you to experiment with a few things hich have been stated in the theory above. The config menu of the screen allows you to configure these variables.

Following table maps the configuration with a variable in the code and what it allows you to experiment with:

Configuration Variable What it does
Draw rectangle fDrawRectangle Allows to choose if you want to draw a rectangle. The variables fDrawLine, fDrawOval and fDrawRing allow you to do the same for an line, oval and ring
Set bounds fSetBounds If set to true, the bounds of the drawables will be set in the code.
As ShapeDrawable fCastToShapeDrawable If set to true, the shape loaded from the resource will first be casted to an object of type ShapeDrawable before its draw-method is called. This will result in an exception being thrown. This variable only has effect when a rectangle is choosen to be drawn.
As GradientDrawable fCastToGradientDrawable If set to true, the shape loaded from the resource will first be casted to an object of type GradientDrawable before its draw-method is called. This variable only has effect when a rectangle is choosen to be drawn.

Drawables in code: CustomDrawableView

public CustomDrawableView(Context context) {
	super(context);

	rectangleDrawable = new ShapeDrawable(new RectShape());
	ovalDrawable = new ShapeDrawable(new OvalShape());
	arcDrawable = new ShapeDrawable(new ArcShape(45, 300));
// Line and Ring are not available. In XML, these come from the GradientDrawable class
//    	lineDrawable = new ShapeDrawable(new OvalShape());
//    	ringDrawable = new ShapeDrawable(new OvalShape());
}

protected void onDraw(Canvas canvas) {
	arcDrawable.getPaint().setColor(0xff74AC23);

	if(fSetBounds)
	{
		rectangleDrawable.setBounds(x, y, x + width, y + height);
		ovalDrawable.setBounds(x, y, x + width, y + height);
		arcDrawable.setBounds(x, y, x + width, y + height);
//    	lineDrawable.setBounds(x, y, x + width, y + height);
//	    ringDrawable.setBounds(x, y, x + width, y + height);
	}
	if(fDrawRectangle)
		rectangleDrawable.draw(canvas);
	if(fDrawOval)
		ovalDrawable.draw(canvas);
	if(fDrawArc)
		arcDrawable.draw(canvas);
//  if(fDrawLine)
//  	lineDrawable.draw(canvas);
//  if(fDrawRing)
//    	ringDrawable.draw(canvas);
}

Again, the config menu allows to experiment with a few settings:

Following variables allow you to experiment with this view.

Configuration Variable What it does
Draw rectangle fDrawRectangle Allows to choose if you want to draw a rectangle. The variables fDrawOval and fDrawArc allow you to do the same for an oval and arc
Set bounds fSetBounds If set to true, the bounds of the drawables will be set in the code.

Transformations using the Matrix class: CustomDrawableMatrixTransformationView

protected void onDraw(Canvas canvas) {
	int rectX = this.getWidth()/2 - (width/2);
	int rectY = this.getHeight()/2 - (height/2);
	rectangleDrawable.setBounds(rectX, rectY, rectX + width, rectY + height);

	//do the same for the oval drawable

	Matrix matrix;
	matrix = new Matrix();

	if(pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER) && pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER))
		matrix.postTranslate(-1 * this.getWidth() / 2, -1 * this.getHeight() / 2);

	int sequence = 0;
	while(pipeline.containsKey("MTX_" + Integer.toString(sequence)))
	{
		Bundle currTransform = (Bundle)pipeline.getParcelable("MTX_" + Integer.toString(sequence));
		String transformationType = currTransform.getString(CustomDrawableMatrixTransformationConfigActivity.TRANSFORMATION_TYPE);
		if(transformationType.equals(MatrixTransformationRotateConfigActivity.TRANSFORMATION_ROTATE))
		{
			float rotation = currTransform.getFloat(MatrixTransformationRotateConfigActivity.ROTATE_ANGLE);
			String transformationOrderType = currTransform.getString(CustomDrawableMatrixTransformationConfigActivity.TRANSFORMATIONORDER_TYPE); 
			if(transformationOrderType.equals(CustomDrawableMatrixTransformationConfigActivity.TRANSFORMATIONORDER_SET))
			{
				matrix.setRotate(rotation);
			}
			if(transformationOrderType.equals(CustomDrawableMatrixTransformationConfigActivity.TRANSFORMATIONORDER_PRE))
			{
				matrix.preRotate(rotation);
			}
			if(transformationOrderType.equals(CustomDrawableMatrixTransformationConfigActivity.TRANSFORMATIONORDER_POST))
			{
				matrix.postRotate(rotation);
			}
		}

		//similar code for translation, scale and skew tranformations

		sequence++;
	}

	if(pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER) && pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER))
		matrix.postTranslate(this.getWidth() / 2, this.getHeight() / 2);

	final Matrix currentMatrix = canvas.getMatrix();

	canvas.concat(matrix);
	if(pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM) && !pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM))
		ovalDrawable.draw(canvas);
	rectangleDrawable.draw(canvas);

	canvas.setMatrix(currentMatrix);
	if(!pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM) || pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM))
		ovalDrawable.draw(canvas);

}

In the above code extract, I only show the code for a rotation. I left out the code for the translation, scaling and skew because it is very similar to that of rotation. You can see the complete code in the attached files.

In the configuration menu you can configure the following:

Configuration Variable What it does
Add New Transform none Allows you concatenate various transformations. If you click this button you will get the following screen allowing you to select the type transformation:

Translate to center TRANSLATETOCENTER Allows you to set the center of the tranformations to the center of the screen, instead of the upper-left corner. This is done by prepending all transformations with a translation to the center of the screen. Afterward, the same translation in the opposite direction is appended.
Translate to center TRANSLATETOCENTER Allows you to set the center of the tranformations to the center of the screen, instead of the upper-left corner. This is done by prepending all transformations with a translation to the center of the screen. Afterward, the same translation in the opposite direction is appended.
Oval out of transform OVALOUTTRANSFORM If set, the drawing of the oval is done outside the transformation. Therefore, the oriiginal transformation matrix of the canvas is saved and restored before drawing the oval.

When selecting a type of transformation you will get the chance to configure other variables:

Configuration Screen What it does
Rotation Rotation has two variables to play with:

  1. order: if the transformation is prepended (pre-method), appended (post-method) or replaces (set-method).
  2. rotation: the angle of rotation around the origin of the screen.
Translation Translation has three variables to play with:

  1. order: if the transformation is prepended (pre-method), appended (post-method) or replaces (set-method).
  2. dX: the translation along the X-axis
  3. dY: the translation along the Y-axis
Scaling Scaling has three variables to play with:

  1. order: if the transformation is prepended (pre-method), appended (post-method) or replaces (set-method).
  2. sX: the scaling along the X-axis
  3. sY: the scaling along the Y-axis
Skew Skew has three variables to play with:

  1. order: if the transformation is prepended (pre-method), appended (post-method) or replaces (set-method).
  2. kX: the skew along the X-axis
  3. kY: the skew along the Y-axis

By using the button it is possible to build a list of transformations to apply, and by selecting the appropriate order of each transformation you can experiment with the order in which the transformations are applied.

Transformations using the Camera class: CustomDrawableCameraTransformationView

protected void onDraw(Canvas canvas) {
	//final Matrix currentMatrix = canvas.getMatrix();

	int rectX = this.getWidth()/2 - (width/2);
	int rectY = this.getHeight()/2 - (height/2);
	rectangleDrawable.setBounds(rectX, rectY, rectX + width, rectY + height);

	//do the same for the oval

	Matrix matrix;
	matrix = new Matrix();

	Camera camera;
	camera = new Camera();

	if(pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER) && pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER))
		//camera.translate(-1 * this.getWidth() / 2, -1 * this.getHeight() / 2, 0);
		matrix.postTranslate(-1 * this.getWidth() / 2, -1 * this.getHeight() / 2);

	int sequence = 0;
	while(pipeline.containsKey("MTX_" + Integer.toString(sequence)))
	{
		Bundle currTransform = (Bundle)pipeline.getParcelable("MTX_" + Integer.toString(sequence));
		String transformationType = currTransform.getString(CustomDrawableCameraTransformationConfigActivity.TRANSFORMATION_TYPE);
		if(transformationType.equals(CameraTransformationRotateXConfigActivity.TRANSFORMATION_ROTATEX))
		{
			float rotationX = currTransform.getFloat(CameraTransformationRotateXConfigActivity.ROTATEX_ANGLE);
			camera.rotateX(rotationX);
		}

		//similar code for roation around Y and Z and for tranlation

		sequence++;
	}   

	Matrix cameraMatrix = new Matrix();
	camera.getMatrix(cameraMatrix);
	matrix.postConcat(cameraMatrix);

	if(pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER) && pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.TRANSLATETOCENTER))
		//camera.translate(this.getWidth() / 2, this.getHeight() / 2, 0);
		matrix.postTranslate(this.getWidth() / 2, this.getHeight() / 2);

	final Matrix currentMatrix = canvas.getMatrix();

	//camera.applyToCanvas(canvas);
	canvas.concat(matrix);
	if(pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM) && !pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM))
		ovalDrawable.draw(canvas);
	rectangleDrawable.draw(canvas);

	canvas.setMatrix(currentMatrix);
	if(!pipeline.containsKey(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM) || pipeline.getBoolean(CustomDrawableMatrixTransformationConfigActivity.OVALOUTTRANSFORM))
		ovalDrawable.draw(canvas);

}

Again, the above code is a stripped down version of the code you can find in the attached files.

The configuration menu allows to experiment with following:

Configuration Variable What it does
Add New Transform none Allows you concatenate various transformations. If you click this button you will get the following screen allowing you to select the type transformation:

Translate to center TRANSLATETOCENTER Allows you to set the center of the tranformations to the center of the screen, instead of the upper-left corner. This is done by prepending all transformations with a translation to the center of the screen. Afterward, the same translation in the opposite direction is appended.
Oval out of transform OVALOUTTRANSFORM If set, the drawing of the oval is done outside the transformation. Therefore, the oriiginal transformation matrix of the canvas is saved and restored before drawing the oval.

When selecting a type of transformation you will get the chance to configure other variables:

Configuration Screen What it does
Rotation around the X-axis Rotation around the X-axis has one variable to play with:

  1. rotation: the angle of the rotation.
Rotation around the Y-axis Rotation around the Y-axis has one variable to play with:

  1. rotation: the angle of the rotation.
Rotation around the Z-axis Rotation around the Z-axis has one variable to play with:

  1. rotation: the angle of the rotation.
Translation Translation has three variables to play with:

  1. dX: the translation along the X-axis
  2. dY: the translation along the Y-axis
  3. dZ: the translation along the Z-axis

Conclusion

As stated in the beginning, the subject of drawing in Android is big. Although the article does not aim at providing all possible information, it does show some basic scenarios and the application in the accompanying source code gives the user the possibility to experiment with these different scenario?s and see how Android response.

Touch handling in Android

September 12, 2012

Sourcecode

You can find the sourcecode over at github:
The Source at github

Introduction

There is allready a lot of information available about touch and multitouch on Android. Consequently, I don’t have the illusion to be providing anything completely new here.

So then why did I write this article?

What I want to try is bundle some information dispersed on the net into a single article and also learn myself by explaining the concepts of touch and multitouch to you. Also, in the provided sourcecode I have made the execution of the code configurable so you can experiment with touch and multitouch on your Android phone, or the emulator if you don’t have a phone.

So, without any further ado:

Background

Single touch

Receiving touch events is done in the view by implementing the overridable method onTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent event) {
	// Do your stuff here
}

Whenever one or a series of touch events are produced, your method will be called with the parameter event providing details on what exactly has happened. Mind that I have written “or a series of touch events” and not “a single touch event”. Android can buffer some touch events and then call your method providing you with the details of the touch events which have happened. I will give more information about this in the section Historic Events.

So, you created the above method, now how do you know what happened?

The type MotionEvent of the argument to your method has the method getAction giving you the kind of touch-action which happened. The main values explained in this article and concerning touch actions are:

  • ACTION_DOWN: You’ve touched the screen
  • ACTION_MOVE: You moved your finger on the screen
  • ACTION_UP: You removed your finger from the screen
  • ACTION_OUTSIDE: You’ve touched the screen outside the active view (see Touch outside the view)

Thus, in your code you use a case statement to differentiate between the various actions

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    	int action = event.getAction();
	switch (action) {
    	case MotionEvent.ACTION_DOWN:
		// Do your stuff here
    		break;
    	case MotionEvent.ACTION_MOVE:
		// Do your stuff here
    		break;
    	case MotionEvent.ACTION_UP:
		// Do your stuff here
    		break;
    	}

    	return true;
    }

Mind that the ACTION_OUTSIDE has nothing to do with moving your finger of the screen. In that case you simply get an ACTION_UP event.

The normal sequence of events is of course ACTION_DOWN when you put your finger down, optionally ACTION_MOVE if you move your finger while touching the screen and finally ACTION_UP when you remove your finger from the screen.

However, if you return false from the onTouchEvent override in respons to an ACTION_XXX event, you will not be notified (your method will not be called) about any subsequent events. Android asserts that by returning false you did not process the event and thus are not interested in any further events. Thus you get following table:

Return false on notification of Receive notification of
ACTION_DOWN ACTION_MOVE ACTION_UP
ACTION_DOWN N.A. NO NO
ACTION_MOVE N.A. N.A. NO
ACTION_UP N.A. N.A. N.A.

As an example: say you returned false from the ACTION_DOWN event, then you will not be notified the ACTION_MOVE and ACTION_UP events.

Other data of MotionEvent

The MotionEvent class has some more methods which provide you with additional information about the event. Those currently supported by the sample application are the screencoordinates of the touchevent and an indication of the pressure with which you pressed on the screen.

Touch events and click and longclick

The basics of click and longclick are af course also touch events and they are implemented in de View implementation of onTouchEvent. This means that if you don’t call the base class implementation, your implementations of onClick and onLongClick will not get called.

@Override
public boolean onTouchEvent(MotionEvent event) {
	// call the base class implementation so that other touch dependent methods get called
	super.onTouchEvent(event);
	// Do your stuff here
}

Alternatively, if you want to do everything yourself, then don’t call the base class implementation.

Multiple Touch

Multitouch is a little more complex than single touch because with single touch the sequence of events is always the same: down, optionally move and eventually up. With multitouch however, you can get multiple consecutive down or up events and the order of the down events, meaning which finger they represent, is not necessary the same as the order of the move and up events.

You can for example put your forefinger, middlefinger and ring finger down, but lift them in the order middlefinger, ring finger and forefinger. In order to keep track of “your finger” Android assigns a pointerid to each event which is constant for the sequence down, move and up.

If your implementation of onTouchEvent is called, Android provides you for each pointer/finger what happened. For multitouch Android does not use the ACTION_DOWN and ACTION_UP codes but instead the ACTION_POINTER_DOWN and ACTION_POINTER_UP. You also must use the method getActionMasked to get the action. You can get the pointerid with following code:

int action = event.getActionMasked();
int pointerIndex = event.getActionIndex();
int pointerId = event.getPointerId(pointerIndex);
// do your stuff

As such, you will not receive any events for these actions containing the data for multiple pointers. Thus when you touch with two fingers at what you think is the same time, Android will produce two calls and therefore there will always be one pointer which is first.

For the ACTION_MOVE however, you can have a single move event for multiple pointers. To get the correct pointerid you must iterate through the provided pointers using the following code:

for(int i = 0; i < event.getPointerCount(); i++)
{
	int curPointerId = event.getPointerId(i);

	// do your stuff
}

Historic events

For ACTION_MOVE, there is not only a list of the events for each pointer, but also a list of ACTION_MOVE events since the last call of your method. Android caches the events which occured during subsequent calls of your onTouchEvent method for ACTION_MOVE events. To get at these events you must use the following code:

for(int j = 0; j < event.getHistorySize(); j++)
{
	for(int i = 0; i < event.getPointerCount(); i++)
	{
		int curPointerId = event.getPointerId(i);

		// in order to get the historical data of the event
		//	you must use the getHistorical... methods
		int x = event.getHistoricalX(i, j);

	}
}

Touch outside the view

To receive the ACTION_OUTSIDE event, you must set two flags for your window:

  • WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL: Indicates that any touches outside of your view will be send to the views behind it.
  • WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH: Indicates that you want to receive the ACTION_OUTSIDE event when touched outside your view.

When these two flags are set on your window, then you will receive the ACTION_OUTSIDE event when a touch happens outside your view.

Do try this at home: the code

The code has 4 views which allow you to experiment with the various use cases. When you start the application you will see the following screen:

Each entry corresponds with a view allowing you to experiment with that feature. Following is an explanation of what entry corresponds with what view/java file and the configurations possible in that view

Graphics Single: TouchVisualizerSingleTouchGraphicView

    @Override
    public void onDraw(Canvas canvas) {
    	if(downX > 0)
    	{
            paint.setStyle(Paint.Style.FILL);
            canvas.drawCircle(downX, downY, touchCircleRadius, paint);
            paint.setStyle(Paint.Style.STROKE);
            canvas.drawCircle(downX, downY, touchCircleRadius + pressureRingOffset + (pressureRingOffset * pressure), paint);
    	}
    }

The onDraw method simply draws two concentric circles at the position where the last event happend. This position is set on the onTouchEvent method shown beneath. The radius of the outer circle is dependend on the pressure with which you touched the screen.

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    	if(callBaseClass)
    	{
    		super.onTouchEvent(event);
    	}

    	if(!handleOnTouchEvent)
    	{
    		return false;
    	}

    	int action = event.getAction();
    	pressure = event.getPressure() * pressureAmplification;

    	boolean result = true;
		switch (action) {
    	case MotionEvent.ACTION_DOWN:
    		downX = event.getX();
    		downY = event.getY();
    		if (returnValueOnActionDown)
    		{
    			result = returnValueOnActionDown;
    		}
    		break;
    	case MotionEvent.ACTION_MOVE:
    		downX = event.getX();
    		downY = event.getY();
    		if (returnValueOnActionMove)
    		{
    			result = returnValueOnActionMove;
    		}
    		break;
    	case MotionEvent.ACTION_UP:
    		downX = -1;
    		downY = -1;
    		if (returnValueOnActionUp)
    		{
    			result = returnValueOnActionUp;
    		}
    		break;
    	case MotionEvent.ACTION_OUTSIDE:
    		break;
    	}
    	invalidate();
    	return result;
    }

	@Override
	public void onClick(View v) {
		Toast msg = Toast.makeText(TouchVisualizerSingleTouchGraphicView.this.getContext(), "onClick", Toast.LENGTH_SHORT);
		msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
		msg.show();
	}

	@Override
	public boolean onLongClick(View v) {
		Toast msg = Toast.makeText(TouchVisualizerSingleTouchGraphicView.this.getContext(), "onLongClick", Toast.LENGTH_SHORT);
		msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
		msg.show();
		return returnValueOnLongClick;
	}

As you can see there are a whole bunch of variables which enable you to configure what the behaviour of the activity. The config menu option of the view allow you to configure these variables

The following table maps these variables to the config setting

Configuration Variable What it does
Call base class callBaseClass If set the base class will be called first. It allows to test OnClick and OnLongClick behaviour.
Handle touch events handleOnTouchEvent If set the rest of the method will be executed. It allows to test the behaviour as if you didn’t override, for this set the variable callBaseClass to true.
True on ACTION_DOWN returnValueOnActionDown The returnvalue of the onTouchEvent method when ACTION_DOWN is received. This allows you to see what other actions you receive when setting this to true or false.
True on ACTION_MOVE returnValueOnActionMove The returnvalue of the onTouchEvent method when ACTION_MOVE is received. This allows you to see what other actions you receive when setting this to true or false.
True on ACTION_UP returnValueOnActionUp The returnvalue of the onTouchEvent method when ACTION_UP is received. This allows you to see what other actions you receive when setting this to true or false.
True on onLongClick returnValueOnLongClick The value returned from the onLongClick method
Pressure amplification pressureAmplification The diameter of the circles shown when putting your finger on the screen is influenced by the pressure with which you press on the screen. This variable allows to amplify this influence.

Graphics Multi: TouchVisualizerMultiTouchGraphicView

    @Override
    public void onDraw(Canvas canvas) {
    	for(EventData event : eventDataMap.values())
    	{
            paint.setColor(Color.WHITE);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawCircle(event.x, event.y, touchCircleRadius, paint);
            paint.setStyle(Paint.Style.STROKE);
            if(event.pressure <= 0.001)
            {
            	paint.setColor(Color.RED);
            }
            canvas.drawCircle(event.x, event.y, touchCircleRadius + pressureRingOffset + (pressureRingOffset * event.pressure), paint);
    	}
    }

The onDraw method iterates through a list which maintainces for each pointer (thus finger) what happened last and draws two concentric circles at the position of each event. This list is maintained in the onTouchEvent method shown beneath. Again, the radius of the outer circle is dependend on the pressure with which you touched the screen.

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    	if(callBaseClass)
    	{
    		super.onTouchEvent(event);
    	}

    	if(!handleOnTouchEvent)
    	{
    		return false;
    	}

    	int action = event.getActionMasked();

    	int pointerIndex = event.getActionIndex();
    	int pointerId = event.getPointerId(pointerIndex);

    	boolean result = true;
		switch (action) {
    	case MotionEvent.ACTION_DOWN:
    	case MotionEvent.ACTION_POINTER_DOWN:
    		EventData eventData = new EventData();
    		eventData.x = event.getX(pointerIndex);
    		eventData.y = event.getY(pointerIndex);
    		eventData.pressure = event.getPressure(pointerIndex) * pressureAmplification;
    		eventDataMap.put(new Integer(pointerId), eventData);
    		if (returnValueOnActionDown)
    		{
    			result = returnValueOnActionDown;
    		}
    		break;
    	case MotionEvent.ACTION_MOVE:
    		for(int i = 0; i < event.getPointerCount(); i++)
    		{
    			int curPointerId = event.getPointerId(i);
	    		if(eventDataMap.containsKey(new Integer(curPointerId)))
	    		{
	        		EventData moveEventData = eventDataMap.get(new Integer(curPointerId));
	        		moveEventData.x = event.getX(i);
	        		moveEventData.y = event.getY(i);
	        		moveEventData.pressure = event.getPressure(i) * pressureAmplification;
	    		}
			}
    		if (returnValueOnActionMove)
    		{
    			result = returnValueOnActionMove;
    		}
    		break;
    	case MotionEvent.ACTION_UP:
    	case MotionEvent.ACTION_POINTER_UP:
    		eventDataMap.remove(new Integer(pointerId));
    		if (returnValueOnActionUp)
    		{
    			result = returnValueOnActionUp;
    		}
    		break;
    	case MotionEvent.ACTION_OUTSIDE:
    		break;
    	}
    	invalidate();
    	return result;
    }

	@Override
	public void onClick(View v) {
		Toast msg = Toast.makeText(TouchVisualizerMultiTouchGraphicView.this.getContext(), "onClick", Toast.LENGTH_SHORT);
		msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
		msg.show();
	}

	@Override
	public boolean onLongClick(View v) {
		Toast msg = Toast.makeText(TouchVisualizerMultiTouchGraphicView.this.getContext(), "onLongClick", Toast.LENGTH_SHORT);
		msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
		msg.show();
		return handleOnLongClick;
	}

The same configuration variables reappear as in the TouchVisualizerSingleTouchGraphicView. You can look in de table there for what they mean.

History Multi: TouchVisualizeMultiTouchHistoricView

    @Override
    public void onDraw(Canvas canvas) {
	    for(List path : eventDataMap.values())
	    {
	    	boolean isFirst = true;
	    	EventData previousEvent = null;
	    	for(EventData event : path)
	    	{
	    		if (isFirst)
	    		{
	    			previousEvent = event;
	    			isFirst = false;
	    			continue;
	    		}
	            paint.setColor(Color.WHITE);
	            if(event.historical)
	            {
	            	paint.setColor(Color.RED);
	            }

	            canvas.drawLine(previousEvent.x, previousEvent.y, event.x, event.y, paint);

	            previousEvent = event;
	    	}
	    }
    }

The onDraw method again iterates a list of events captured in the onTouchEvent method. However, all events originate from a single tocuh down, move and up sequence. If it is a historical event, the line is drawn in red, otherwise the line is white.

    @Override
    public boolean onTouchEvent(MotionEvent event) {
   		super.onTouchEvent(event);

    	boolean result = handleOnTouchEvent;
    	int action = event.getActionMasked();

    	int pointerIndex = event.getActionIndex();
    	int pointerId = event.getPointerId(pointerIndex);

		switch (action) {
    	case MotionEvent.ACTION_DOWN:
    	case MotionEvent.ACTION_POINTER_DOWN:
    		EventData eventData = new EventData();
    		eventData.x = event.getX(pointerIndex);
    		eventData.y = event.getY(pointerIndex);
    		eventData.pressure = event.getPressure(pointerIndex);
    		List path = new Vector();
    		path.add(eventData);
    		eventDataMap.put(new Integer(pointerId), path);
    		break;
    	case MotionEvent.ACTION_MOVE:
    		if(handleHistoricEvent)
    		{
	    		for(int j = 0; j < event.getHistorySize(); j++)
	    		{
		    		for(int i = 0; i < event.getPointerCount(); i++)
		    		{
		    			int curPointerId = event.getPointerId(i);
			    		if(eventDataMap.containsKey(new Integer(curPointerId)))
			    		{
			    			List curPath = eventDataMap.get(new Integer(curPointerId));
			        		EventData moveEventData = new EventData();
			        		moveEventData.x = event.getHistoricalX(i, j);
			        		moveEventData.y = event.getHistoricalY(i, j);
			        		moveEventData.pressure = event.getHistoricalPressure(i, j);
			        		moveEventData.historical = true;

			        		curPath.add(moveEventData);
			    		}
					}
	    		}
    		}
    		for(int i = 0; i < event.getPointerCount(); i++)
    		{
    			int curPointerId = event.getPointerId(i);
	    		if(eventDataMap.containsKey(new Integer(curPointerId)))
	    		{
	    			List curPath = eventDataMap.get(new Integer(curPointerId));
	        		EventData moveEventData = new EventData();
	        		moveEventData.x = event.getX(i);
	        		moveEventData.y = event.getY(i);
	        		moveEventData.pressure = event.getPressure(i);
	        		moveEventData.historical = false;

	        		curPath.add(moveEventData);
	    		}
			}

    		if(pauseUIThread != 0)
    		{
	    		try {
					Thread.sleep(pauseUIThread);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
    		}

    		break;
    	case MotionEvent.ACTION_UP:
    	case MotionEvent.ACTION_POINTER_UP:
    		eventDataMap.remove(new Integer(pointerId));
    		break;
    	case MotionEvent.ACTION_OUTSIDE:
    		break;
    	}
    	invalidate();
    	return result;
    }

To simplefy things a bit here, I removed the configuration variables from the previous views and just left in two variables which allow you to experiment with the historical events.

Configuration Variable What it does
Handle historic events handleHistoricEvent If set, historical events will also be added to the list of events
Pause UI Thread pauseUIThread A value indicating, in milliseconds, how long the UIThread will be paused during processing of onTouchEvent. If you set this longer, more events should be cached as historical events by Android.

Dialog: TouchVisualizerSingleTouchDialog

    public TouchVisualizerSingleTouchDialog(Context context) {
        super(context);

        registerForOutsideTouch = ((TouchVisualizerSingleTouchDialogActivity)context).getRegisterForOutsideTouch();
        handleActionOutside = ((TouchVisualizerSingleTouchDialogActivity)context).getHandleActionOutside();

        if(registerForOutsideTouch) {
	        Window window = this.getWindow();
	        window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
	        window.setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
        }

        this.setContentView(R.layout.custom_dialog);
		this.setTitle("Custom Dialog");
    }

    public boolean onTouchEvent(MotionEvent event)   {
    	if (handleActionOutside) {
	    	if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
	    		this.dismiss();
	    	}
    	}

    	return false;
    }

Here also there are configuration variables which allow you to play with this use case.

Configuration Variable What it does
Register outsidetouch registerForOutsideTouch To receive ACTION_OUTSIDE events, you must register for them in the constructor of your view. This variable enables you to do this.
Handle ACTION_OUTSIDE handleActionOutside Of course, you must also handle the ACTION_OUTSIDE event.

Conclusion

A lot has been written already about multitouch in Android. Allthough the article does not aim at providing any new information, the application in the accompaning sourcecode gives the user the possibility to experiment with different scenario’s and see how Android respons.

External references

How to use Multi-touch in Android 2

Google changed the base URL for retrieving tiles, so hit that “Retrieve” button in the Offline Maps application to be able to continue to use it.

For those that want to do it manually, see the URL table on the Offline Maps project page

Good luck !!

About stubs, fakes and mocks

September 2, 2009

Test driven development is not an easy subject. And to be honest, I’ve not been convinced of it’s usefullness when first reading about it, witnessing this post. What I do believe firmelly is the usefulness of unit testing. But I have found that overall resistance to unit testing is rather big mostly because if not done well it turns out to be rather timeconsuming.

Now, let me start by saying I’m not an expert on the subject. I’ve tried applying it to some projects with some success and wanted to use it extensively in the next major release of my Offline Maps project. So I did some research to find where I could improve and my first subject was mock objects.

It turned that mocks are only a part of the complete picture.

Ok mocks, but what about stubs, dummies, fakes, etc…

There is a lot of lingo surrounding unit testing. Before we get any deeper on mock objects lets clearly define what they are and more importandly, what they are not and what differentiates them from stubs, fakes, etc…

Stubs

According to Jeremy Miller, the difference between mocks and stubs is mostly in the sort of testing you’re performing:

The real difference between a mock and a stub is in the style of unit testing, i.e. state-based testing versus interaction testing. A stub is a class that is hard-coded to return data from its methods and properties. You use stubs inside unit tests when you’re testing that a class or method derives the expected output for a known input.

Gerard Meszaros provides a bit more detail:

In many circumstances, the environment or context in which the system under test (SUT) operates very much influences the behavior of the SUT. To get good enough control over the indirect inputs of the SUT, we may have to replace some of the context with something we can control, a Test Stub.

So, you use stubs if you want to provide data to your system under test and the outcome of your system under test is dependend on the content of that data. A good example would be an object which has as input the current date and for example calculates yesterday. If you where to use the effective current date, then you could never write a test because each different day you execute the test would use a different current day, thus calculate a different yesterday and thus the value against which you want to check would change every day. If you however create a stub which provides a current day that you can set fixed, then you can reproduce the result whenever you want:

An example:

The code we want to test is the following:

public ITodayProvider TodayProvider { get; set; }
public DateTime Yesterday 
{
	get { return TodayProvider.Today.AddDays(-1); } 
}

The implementation of ITodayProvider used in the application uses the system date:

public DateTime Today
{
	get { return DateTime.Today; }
}

The implementation of ITodayProvider used in the test however allows to set the date that will be returned:

public DateTime Today
{
	get;
	set;
}

The test with the ITodayProvider using the system date does not produce repeatable results:

[Test]
public void WithoutStubTest()
{
	CalculateYesterday yesterdayCalculator = new CalculateYesterday();
	yesterdayCalculator.TodayProvider = new TodayProvider();

	// Unless you execute this test exactly on 1st september 2009, this test will fail
	Assert.AreEqual(new DateTime(2009, 8, 31), yesterdayCalculator.Yesterday);
}

The test with the ITodayProvider which can be set does allow to produce repeatable results:

[Test]
public void WithStubTest()
{
	CalculateYesterday yesterdayCalculator = new CalculateYesterday();
	TodayProviderStub stub = new TodayProviderStub();
	stub.Today = new DateTime(2009, 9, 1);
	yesterdayCalculator.TodayProvider = stub;

	// This test will always succeed, that is if you implementerd the yesterday calculation correctly.
	// It is however completely independent of the day the test is executed
	Assert.AreEqual(new DateTime(2009, 8, 31), yesterdayCalculator.Yesterday);
}

Fakes

Where a stub actually influences the system undertest, a fake only “fakes” an object in the system under test. Again according to Gerard Meszaros:

The SUT often depend on other components or systems. The interactions with these other components may be necessary but the side-effects of these interactions as implemented by the real depended-on component (DOC), may be unnecessary or even detrimental. A Fake Object is a much simpler and lighter weight implementation of the functionality provided by the DOC without the side effects we choose to do without.

Matin Fowler in his post on different kinds of test doubles states the following:

Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example) So whereas stubs don’t have any working functionality, fakes have. They just take some shortcuts. Stubs are typically hardcoded to return some value.

As an example, suppose your object uses a webservice for retrieving some values, you may not be interested in setting up a connection to the webservice, provide a connection string, etc… because the actual webservice used is unimportant to your system under test. You also don’t want everyone executing your tests to be dependend on the availability of that webservice or detrimental behaviour like unavailable connections, timeouts and all that sort of stuff specific to webservices to mess up your test. In this case you could use a fake in webservice which provides the same functionality but is much easier in setup and which doesn’t exhibit the unwanted behaviour of unavailable connections and timeouts.

The code we want to test is the following:

public ITodayProvider TodayProvider { get; set; }
public IDayRangeCalculatorService DayRangeService { get; set; }
public DateTime YesterdayUsingDayRangeService
{
	get 
	{
		IDayRangeCalculator dayRangeCalculator = DayRangeService.ConnectToService();
		int daysBetween = dayRangeCalculator.DaysBetweenTodayAndYesterday();

		return TodayProvider.Today.AddDays(daysBetween); 
	}
}

A fake implementation of the service allows to get away of all problems relating to connecting to and using of webservices:

class DayRangeCalculatorServiceFake : IDayRangeCalculatorService
{
	#region IDayRangeCalculatorService Members

	public IDayRangeCalculator ConnectToService()
	{
		return new DayRangeCalculatorFake();
	}

	#endregion
}

class DayRangeCalculatorFake : IDayRangeCalculator
{
	#region IDayRangeCalculator Members

	public int DaysBetweenTodayAndYesterday()
	{
		return -1;
	}

	#endregion
}

By using the fake in the test we know our test will not fail because of problems related to the webservice. So if our test fails, then we know it’s because our algoritme failed:

[Test]
public void WithDaysBetweenServiceFakeTest()
{
	CalculateYesterday yesterdayCalculator = new CalculateYesterday();
	TodayProviderStub stub = new TodayProviderStub();
	stub.Today = new DateTime(2009, 9, 1);
	yesterdayCalculator.TodayProvider = stub;

	yesterdayCalculator.DayRangeService = new DayRangeCalculatorServiceFake();

	// In this test we are only interested if the method returns the correct yesterday 
	//  and not if the logging was done correctly
	Assert.AreEqual(new DateTime(2009, 8, 31), yesterdayCalculator.YesterdayWithLogging(new LoggingDummy()));
}

Dummies

Dummies have no influence at all on the tests. They are just used to provide values for method parameters, etc…

Fowler:

Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.

Thus, you use a dummy if you test requires an object which thus not have any influence on the outcome of your test. An example could be a method called in your test which has some specific outcome you want to check but for example also take a logging object as a parameter. Remember we are unit testing and each test checks on some aspect of the object. So we want to check the specific outcome of calling the method but in this test we are not at all interested in the logging of the method. Then we provide a dummy logging object which actually thus nothing but allows us to call the method and check the expected outcome.

The code we want to test is the following:

public ITodayProvider TodayProvider { get; set; }

public DateTime YesterdayWithLogging(ILogging logging)
{
	logging.LogMessage("Executing YesterdayWithLogging");
	return TodayProvider.Today.AddDays(-1);
}

In our test we don’t care about logging. So we provide a dummy logging class which does nothing:

class LoggingDummy:  ILogging
{
	#region ILogging Members

	public void LogMessage(string message)
	{
	}

	#endregion
}

In our test we don’t have to worry about the logging

[Test]
public void WithLoggingDummyTest()
{
	CalculateYesterday yesterdayCalculator = new CalculateYesterday();
	TodayProviderStub stub = new TodayProviderStub();
	stub.Today = new DateTime(2009, 9, 1);
	yesterdayCalculator.TodayProvider = stub;

	// In this test we are only interested if the method returns the correct yesterday 
	//  and not if the logging was done correctly
	Assert.AreEqual(new DateTime(2009, 8, 31), yesterdayCalculator.YesterdayWithLogging(new LoggingDummy()));
}

Now, if all this is a bit overwhelming, don’t be concerned. Your test doubles will mostly be a mix of the above, or their focus or purpose will shift as shown by Daniel Cazzulino in his postMocks, Stubs and Fakes: it’s a continuum .

Mock objects, what problems to they solve ?

In many posts about the type of test doubles there is also the difference between test spies and mocks. From what I could find on them the difference is not that clear to me. So I will treat them as being the same. Of course, if you can explain the difference in a clear way, you’re welcome, or if you know a reference let me know.

About behaviour

We all know it but lets state it once more explicitely:
Objects are instances of classes which exhibit both state and behaviour.

Anyone studying UML will agree that both the class diagram and the sequence diagram are needed to document the interactions of systems. Where the class diagram shows what properties the classes in the system have, the sequence diagram shows what the important method calls made by the objects are. So you could say that the class diagram documents the state of a system (not entirely thru) and the sequence diagram documents the behaviour of the system. And as you need both the class diagram and the sequence diagram you need both state testing and behaviour testing.

When to use mock objects

The main difference with traditional testing is that where traditional testing allows a more state-based approach of testing, mock objects provide a behaviour style of testing. We all know the traditional style of unit testing using frameworks like NUnit, MbUnit and there assert-style testing:

  1. Setup your test
  2. Execute some action
  3. Assert that the properties of the object under test are what you expect

We assert that the state the object under test is in, is what we expect. To check this state, we check the values of the object’s properties.

Behaviour style testing on the other hand verifies the dynamic behaviour of the object under test. Remember that we are using mock objects to represent companion objects “on the edges of the object under test”. That is, objects used by our object under test. Now, sometimes we will want to know if our object under test calls a certain method with certain arguments of the companion object. The post Using Mock Objects Effectively provides a great example:

On closer inspection, it becomes clear that the application is not actually logging anything. Log4J is responsible for doing that. What the application is truly doing is sending a signal (a request) to log4j to log a message. That distinction is *very* important. The appropriate test then is simply to verify that the application is sending the correct signal to the service provider under the right conditions.

We now get following test sequence:

  1. Setup your test
  2. Execute some action
  3. Assert that the required methods have been executed with the correct parameters and in the correct sequence

We assert that the object under test executed the behaviour we expect. To check this behaviour, we check the methods it called and the arguments it provided to those methods.

So, using mock objects for behavioural testing can co-exist with the more traditional style of sate based testing.

Martin Fowler, him again, warns for some caveats when using mock style testing in his article Mocks Aren’t Stubs:

When you write a mockist test, you are testing the outbound calls of the SUT to ensure it talks properly to its suppliers…
Coupling to the implementation also interferes with refactoring, since implementation changes are much more likely to break tests than with classic testing.

An example

The code we want to test is the following:

public ITodayProvider TodayProvider { get; set; }

public DateTime YesterdayWithLogging(ILogging logging)
{
	logging.LogMessage("Executing YesterdayWithLogging");
	return TodayProvider.Today.AddDays(-1);
}

In our test we don’t care about the exact output of the logging but we do care if the logging is called and if it is called with the correct arguments. So we want to record the methodcall and the arguments with which it got called:

class LoggingMock:  ILogging
{
	public int NumberOfMethodCalls { get; private set; }
	public List<String> MethodCallArguments { get; private set; }

	#region ILogging Members

	public void LogMessage(string message)
	{
		NumberOfMethodCalls++;
		if (MethodCallArguments == null)
		{
			MethodCallArguments = new List<string>();
		}

		MethodCallArguments.Add(message);
	}

	#endregion
}

By recording the calls we can check in our test if the method got called and if the provided arguments where correct:

[Test]
public void WithLoggingMockTest()
{
	CalculateYesterday yesterdayCalculator = new CalculateYesterday();
	TodayProviderStub stub = new TodayProviderStub();
	stub.Today = new DateTime(2009, 9, 1);
	yesterdayCalculator.TodayProvider = stub;
	LoggingMock loggingMock = new LoggingMock();

	// In this test we want to see if the logging is called correctly
	DateTime yesterday = yesterdayCalculator.YesterdayWithLogging(loggingMock);

	Assert.AreEqual(1, loggingMock.NumberOfMethodCalls);
	Assert.AreEqual("Executing YesterdayWithLogging", loggingMock.MethodCallArguments[0]);
}

Sample Code

The Code

Links

Mock Objects and Stubs: The Bottle Brush of TDD
Why and When to Use Mock Objects
Best and Worst Practices for Mock Objects
xUnit Patterns
Using Mock Objects Effectively
MF Bliki: TestDouble
Mocks Aren’t Stubs
Mock object

In this first post on new C# language features I will write about Optional Parameters and Named Parameters for methods.

Past and Present

In the current and previous versions of C#, if you wanted to give users of your API the ability to use a method with a different number of parameters you had to overload a method:

    public void OldFashionedMethod(string stringParam, int intParam)
    {
      Console.WriteLine("OldFashionedMethod(two parameters) - The parameters are: stringParameter[{0}] intParameter[{1}]",
        stringParam, intParam);
    }

    public void OldFashionedMethod(string stringParam)
    {
      int intParam = 8;
      Console.WriteLine("OldFashionedMethod(one parameter) - The parameters are: stringParameter[{0}] intParameter[{1}]",
        stringParam, intParam);
    }

This allows you to call the method in two ways

SomeClass.OldFashionedMethod("TheParameter", 10);
SomeClass.OldFashionedMethod("TheParameter");

You could of course also use this technique

Future

In th enext version of C# you will be able to provide default values for the parameters of a method, in the declaration of that method

    public void OptionalParameterMethod(string stringParam, int intParam = 8)
    {
      Console.WriteLine("The parameters are: stringParameter[{0}] intParameter[{1}]",
        stringParam, intParam);
    }

This also allows you to write similar as above:
This allows you to call the method in two ways

SomeClass.OptionalParameterMethod("TheParameter", 10);
SomeClass.OptionalParameterMethod("TheParameter");

If it looks like a duck …

If we perform the Duck test on this code we will come to the conclusion that although the code looks the same, the behaviour is different so both probably aren’t ducks.

Using Reflector we can look at how the above is resolved by the compiler:

In the case of overloaded method, the compiler generates the expected method calls, one for each overoaded version:

SomeClass.OldFashionedMethod("TheParameter", 10);
SomeClass.OldFashionedMethod("TheParameter");

However, in the case of default parameter values, the compiler generates calls to the single methods and injects the default parameter value when compiling the call making use of the default parameter:

SomeClass.OptionalParameterMethod("TheParameter", 10);
SomeClass.OptionalParameterMethod("TheParameter", 8);

So the default parameter is not substituted in the method itself, like it is done when using overloaded methods, but it is resolved at the call site.

In practice this means that when the writer of the library changes the value of the default parameter, your code calling this library will not use this new value, unless you recompile your code.

So, what isn’t possible?

Optional parameters are only possible at the end of the parameterlist of a method. So, you can not do the following:

public void OptionalParameterMethod(string stringParam = "DefaultValue", int intParam)

From the above code you might wonder why this isn’t possible, but have a look at the folowing method declaration:

public void OptionalParameterMethod(string stringParam = "DefaultValue", string otherStringParam)

Now, how must the compiler resolve following call?

SomeClass.OptionalParameterMethod("TheParameter");

Is the provided parameter a substitute for the default parameter, or is it a value for the last parameter?

Optional parameters can only be compile time constants. This makes the following impossible:

public void DefaultClassParameter(ParameterClass param = new ParameterClass())

The fact that only compile time constants can be used, limits the use of optional parameters to primitive types, enums, or strings.

Usefull or useless

Optional parameters generally generate some of fuss when discussed because most implemetations use the resolve at call site approach which can produce some unexpected results when the library exposing the method evolves and the default value changes. This article provides some guidance

What started as a simple concept, Delegates and Events, has turned into a major subject in the .NET framework with newcommers like Anonymous Methods and Lambda Expressions. In this post I hope to shed some light on what all these are and how they interact. Mind you however that all that is written in this post is not new and has been described in more detail by many other much more smarter people then me. So, allthough I will touch on the various aspects of the subject, for detailed discussions and how certain features work I will forward you to those posts. It is not my goal to repeat what allready has been said, but I wanted investigate what is possible and share my results with you. This way I thought to provide in one post a detailed summary on what is possible and how it’s done.

It is my hope that after reading this post and reading the referenced articles, one would have an in depth knowledge of delegates, events and the lot.

Delegates

The basic construct for all the above is the delegate. For those familiar with C++: a delegate can be seen as similar to a function pointer in that it allows you to pas a reference to a method around and then later call that method. There are however some differences between them resulting in people trying to emulate delegates in C++

For those unfamiliar with C++, this Stack Overflow article has a nice explanation:

The best analogy that I’ve found to explain delegates it’s a testament or your last will.

It’s a set of instructions that of course you write before you die, and you leave it in a safe place. Then after your death, your attorney will execute those instructions…

Delegates are used mostly when the code that wants to execute the actions doesn’t knows the enough details of what that action should be, you can view it as a sequence of actions to be executed at the appropriate time.

Declaring a delegate

Declaration of a delegate is done in C# using the delegate keyword:

// A delegate is a type of itself, so you
// can declare it outside the scope of a class
delegate int SomeMethodDelegate(string arg);

This declaration declares a delegate which can call methods that return an integer and have a string as their single argument. A delegate is a type of it’s own, so a delegate can be declared outside the scope of a class unlike methods and properties. But just as a type (class, struct, …) can not be declared inside a method, neither can a delegate. If you declare a delegate using the above syntax, you are actually declaring a type derived from the Delegate type. Actually, it’s derived from the System.MulticastDelegate type.

Using the delegate

Instantiating the delegate and binding a method to it is as simple as:

// Provided you have an object delegateDemo of a class which implements 
// a method called MethodCall which takes a string and returns an integer
SomeMethodDelegate delegateReference = new SomeMethodDelegate(delegateDemo.MethodToCall);

Using the delegate is similar to invoking the method

int i = delegateReference("String argument");

There is a more longwinded way of instantiating delegates and invoking them directly involving the Delegate class. I will not illustrate it here but you can find more information about it in the Stackoverflow question “Possible to instantiate and invoke a delegate by name?”

Delegates are “Multicast”

In the .Net framework, delegates are multicast. What this means is that you can bind more then one method to a delegate:

SomeMethodDelegate delegateReference = new SomeMethodDelegate(delegateDemo.MethodToCall);
delegateReference += new SomeMethodDelegate(delegateDemo.SomeOtherMethodToCall);

If you now invoke the delegate, the two methods bound to the delegate will be called. If a method in the chain throws an exception, latter methods will no longer be called. You can avoid this by iterating the multicast delegate invocation list yourself.

Life made easy

Delegates are practical beasts and you can use them in lot’s of places. To help you and to prevent you’d have to declare new delegate types all over the place, Microsoft declared some delegate types in the .Net Framework which you can use out of the box:

Action Delegate 
Action<T> Generic Delegate 
...
Action<T1, T2, T3, T4> Generic Delegate

These encapsulate methods with no return value and zero to 4 arguments.

So, whenever you find the need to write code like

delegate void YourDelegate(int, double, string);
YourDelegate yourDelegateInstance;

you can instead write:

Action<int, double, string> yourDelegateInstance;
Func<TResult> Generic Delegate 
Func<T, TResult> Generic Delegate 
...
Func<T1, T2, T3, T4, TResult> Generic Delegate 

These encapsulate methods with a return type and zero to 4 arguments.

You can find more about predefined delegates here.

Deep dive

There is also another, more powerfull, way of instantiating delegates. If you take a look at the MSDN documentation of the Delegate type, then you will see it has a method CreateDelegate which has a number of overriden signatures of which Delegate.CreateDelegate Method (Type, Object, MethodInfo, Boolean) is the most generic one. Where in the above samples the assignment of the delegate also specifies the object to call the method from, with this method it is possible to postpone this decision untill you actually call the instantiated delegate, by providing the object as an argument to the delegate.

delegate void OpenMethodDelegate(DelegateDemo target);

class DelegateDemo
{
  public DelegateDemo(string arg)
  {
    m_arg = arg;
  }

  public void MethodToCall()
  {
    Console.Write("This method got called on object DelegateDemo[" + m_arg + "] using a delegate.\n");
  }
}
	
MethodInfo method = typeof(DelegateDemo).GetMethod("MethodToCall", BindingFlags.Public | BindingFlags.Instance);
OpenMethodDelegate nonBoundDelegate = (OpenMethodDelegate)Delegate.CreateDelegate(typeof(OpenMethodDelegate), null, method);
DelegateDemo delegateDemo1 = new DelegateDemo("delegateDemo1");
nonBoundDelegate(delegateDemo1);
DelegateDemo delegateDemo2 = new DelegateDemo("delegateDemo2");
nonBoundDelegate(delegateDemo2);

With the above delegate declaration, you can create 4 different delegate instantiations, all documented here. In the sample code with this post you can see an implementation of the 4 possibilities.

Events

Events are technically essentialy the same as delegates, only they have been declared with the modifier “event”. Thus, they are a special kind of delegate: a “modified” delegate. However they serve a different semantic purpose.

Declaring an event

Because an event is a special kind of instance of a or is a modified delegate, you declare events as a special type of instance of the delegate.

delegate int SomeMethodHandler(string arg);
public event SomeMethodHandler SomeMethodEvent;

You could compare it with declaring a const:

int i;		   // The normal type (in the above this is the delegate)
const int j;	// The modified type (in the above this is the event)

The type of modification it does is however completely different. (and then again, it’s not, but you will read about this further).

Using the delegate as an event

Instantiating the event and binding it to a method is done like:

eventDemo.SomethingHappenedEvent += new EventDelegate(eventDemo_SomethingHappenedEvent);

Notice how we used the “+=” operator instead of the simple assignment operator as done with regular delegates. This is one of the effects of using the event modifier on the delegate. What actually happens when you use the event modifier on a delegate is the following:

  1. A field is created on your class with the type of the delegate.
  2. “Add” and “Remove” accessor methods are created to access that field. These two methods are generaly called “Event Accessors”

This is much in the same way as when you declare a property to access a field. This is also why the above descibes the implementation of what is called “Field like events”. The above syntax is a C# shortcut for accessing those add and remove handlers.

Using the event-delegate is similar to invoking a method.

SomethingHappenedEvent();

What is not visible in this code is the fact that this call can only be made inside a method of the class declaring the event. The event field can not even be accessed in a class deriving from the class declaring the event. This also is an effect of using the event modifier on the delegate instance.

If you want to provide access to derived classes, Microsoft suggests declaring so called “On” handler methods:

event MyCorrectEventHandler MyCorrectEvent;
event EventHandler<MyCorrectEventArgs> TheSameButWithoutTheDelegate;

protected virtual void OnMyCorrectEvent(MyCorrectEventArgs e)
{
  EventHandler<MyCorrectEventArgs> handler = TheSameButWithoutTheDelegate;
  if (handler != null)
  {
    e.SomeValue = 1;
    handler(this, e);
  } 
}

In the derived class, you then raise the event by calling this On… method.

The “event” modifier: what does it do?

The event keyword in C# is actually a modifier on the delegate type. What it modifies is the visibility of certain members of the delegate so that effectively you can only access the Combine and Remove methods of the Delegate type, that being the reason why you can only add or remove delegate handlers.

Some conventions

The above code, allthough correct, is not the common way of using events. Microsoft provides some guidelines on how to declare and use event in the .NET Framework:

  • The delegate for the event has no return value.
  • The delegate for the event always has two parameters, the first of type object and referencing the object that fires the event, and the second an EventArgs derived class which identifies details of the event.

In the above you will probably recognize the typical eventhandler signature from windows forms:

void button_ClickHandler(object sender, System.EventArgs e)

Life made easy

When make heavy use of events in your code, you will find yourself declaring lots of events. That would require you to also write lots of delegates for those events, all with this same basic structure of a method taking an object and a EventArgs derived class.

To make life easier Microsoft provides two delegate for you to prevent this clutter:

EventHandler Delegate 
EventHandler<TEventArgs> Generic Delegate 

So instead of having to write

delegate void MyPersonalEventHandler(object sender, EventArgs e);
event MyPersonalEventHandler MyPersonalEvent;

You can now write

event EventHandler MyPersonalEvent;

Or if you have your own event arguments:

class YourEventArgs : EventArgs {... }
event EventHandler<YourEventArgs> YourEventWithSpecialArguments;

Deep dive
The above illustrates the most common way of using the event modifier on delegates. If you look at the documentation for the event modifier you will notice that there is also the possibility of declaring events as virtual, abstract, etc… Whereas the event modifier changes the visibility of certain members of the delegate, declaring an event as virtual or abstract actually changes the the implementation of the event much in the same way as declaring a property as virtual or abstract.

Just as a abstract or virtual properties provide just the signature for the property getter and setter methods, an abstract or virtual event provides just the signature for the event “add-er” and “remove-er” methods.

You can then provide your own implementations for the event accessor methods. Being able to provide your own accessor methods implementations is however not a privilege for abstract and virtual events, but can be done for every event.

Again, in the sample code you can see an implementation of this.

Anonymous methods

Since C# 2.0 there is a new syntax for attaching methods to delegates named Anonymous methods. Well, this is actally an over-simplification of anonymous methods. But let’s stick with this simplification for a minute.

Declaring an anonymous method

In the Delegate section you learned that attaching a method to a delegate is done by creating the method in a class first and then assigning that method to the delegate:

delegate int SomeMethodDelegate(string arg);

class ClassWithMethod
{
   int MethodToCall(string arg) { ... }
}

SomeMethodDelegate delegateReference = new SomeMethodDelegate(delegateDemo.MethodToCall);

This can be cumbersome because it obligates you to create a method in a class which you will not always want to do. So C# 2.0 provides you the possibility to declare that method inline with the assignment to the delegate:

SomeMethodDelegate d = delegate(string param) { Console.WriteLine("Param: " + param.ToString()); };
d("A Parameter");

This can be very handy in certain situations like sorting of items in a list.

Deep dive

Now why is this an oversimplification? Because with the syntax of Anonymous Methods comes a programming construct more generaly known as Closures to C#.

What closures allow you to do is use the variables known in the scope declaring the anonymous method, inside the anonymous method. As an example:

public static void UsingLocal()
{
  int i;
  i = 1; 
  Action d = delegate(int param) { Console.WriteLine("With Parameters[" + param.ToString() + "] and Local[" + i.ToString() + "]"); };
  d(2);
}

This even extends to the fields of the class in which the declaring scope resides:

class AnonymousMethodDeepDive
{
  private int m_field;

  public AnonymousMethodDeepDive(int field)
  {
    m_field = field;
  }

  public int Property { get; set; }

  public void UsingField()
  {
    Action d = delegate(int param) { Console.WriteLine("With Parameters[" + param.ToString() + "] and Field[" + m_field.ToString() + "]"); };
    d(1);
  }

  public void UsingProperty()
  {
    Action d = delegate(int param) { Console.WriteLine("With Parameters[" + param.ToString() + "] and Property[" + Property.ToString() + "]"); };
    d(1);
  }
}

What essentialy happens is:

  1. The compiler generates a class, capturing all the local variables as proeprties of that class.
  2. The compiler generated class has as a method the anonymous method, thus making it’s properties (and thus tha variables in the decalring scope) available to the anonymous method.

There are a few optimizations in some special cases, but the above is the most generic way to look at these.

Now, if you think you understand all this, then read these two posts.

Lambda Expressions

Lambda Expressons are in their most basic form a more convenient syntax for anonymous methods. Again, their is a lot more to lambda expressions then this, but those features have nothing to do with delegates so I will not discuss them in this post.

Syntax

The most generic way for writing lambda expressions is:

Func f1 = (int x, string y) =&gt; { Console.WriteLine("A Return Value And Two Parameters: " + x.ToString()); return x + 1; };

In this assignment statement the form

() => { }

is the lambda expression.

Now, there are a few simplifications possible:

Because C# supports parameter type inference, you can drop the type specifiers for the arguments:

Func f1 = (x, y) => { Console.WriteLine("A Return Value And Two Parameters: " + x.ToString()); return x + 1; };

If you have a single statement, you can drop the curly braces and the semicolon:

Action d4 = (x, y, z) => Console.WriteLine("Three Parameters: [{0}][{1}][{2}]", x, y, z);

If you have a single parameter, you can drop the parameter braces:

Action d2 = x => { Console.WriteLine("One Parameter: " + x.ToString()); };

If you have a single statement, which is the return value, you can drop the “return” keyword:

Func f2 = x => x + 1;

Code

You can download the code here

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: