Wednesday, April 24, 2013

Long running tasks in App Inventor Components

(Many thanks to Mark Friedman from Google for his review and great comments).

As mentioned in the post about the UI thread, App Inventor is basically a UI centric system, in the sense that everything happens within a Screen. For this reason, when tasks that might take a bit of time to finish are required, they should be done in their own thread, or otherwise the full UI will come to a halt until the task finishes up.

Examples of long running tasks could be, among others, any operations that need access to external resources, such as the calls in the Web component, the calls to the Twitter API, calls to reading from the SD card, sending or retrieving data in TinyWebDB calls, and so on.

So how can these kind of operations be dealt with? Mainly by dividing the process into two stages, a first part that spins a new thread to deal with the operation itself, and a second part that can trigger an event back in the UI thread, once the operation is finished. This is the core idea behind Event-Driven Architectures or Event-Driven Programming, and most toolkits for creating graphical interfaces use it widely.

According to Wikipedia, Event-driven Programming can be defined as:
[...] an application architecture technique in which the application has a main loop which is clearly divided down to two sections:
  • the first is event selection (or event detection)
  • the second is event handling.
Let’s see it with a concrete example; Think about how the Web component in App Inventor works:
Part 1: Call Get : Part 2: when GotText gets triggered, handle it.

The user will place a Web.Get call block in a handler(such as a button click), and configure the component with the URL to be accessed. That is part 1 of our event-driven design. For part 2, the user needs to place a Web.GotText event block (or Web.GotFile) in the blocks editor, and they are assured that when this event is triggered, they can access the contents of the resource they had asked for (as well as the response code and type).

In programming terms, for a component developer, the Web.Get call block will have to create and launch a new thread to grab the resource that the user wants from the Internet. Once the resource is retrieved, this new thread will communicate back to the app by triggering the Web.GotText event in the UI thread. Let’s see this in code.

First part: running a new thread with the request
  @SimpleFunction
  public void Get() {
    [... some config code here ...]

    AsynchUtil.runAsynchronously(new Runnable() {
      @Override
      public void run() {
        try {
          performRequest(webProps, null, null);
        } [... exception handling code here ...]
      }
    });
  }

The main thing we want to observe here is that the call to performRequest is done inside a Runnable object, which will be a thread spawning from the UI thread. This is step 1 of our event-driven design. Whatever we need to do in this method, and however long it takes, is not a concern anymore (to a certain extent!) because it will be performed outside of the UI thread.

Second part: processing the request and going back to the UI thread
Lets see now what the performRequest method does, and how it connects back to the UI thread:

  private void performRequest(final CapturedProperties webProps, byte[] 
    postData, String postFile) throws IOException {

    // Open the connection.
    HttpURLConnection connection = openConnection(webProps);
    if (connection != null) {
      try {
        if (postData != null) {
          writePostData(connection, postData);
        } [... other code to write to file ...]   
        [... some more code to deal with the data; note that this code, and
             other actions such as opening a HTTP connection at the top of
             this method, can take a long time ...]
          // Dispatch the event.
          activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
              GotText(webProps.urlString, responseCode, responseType, path);
            }
          });
        [... more code to handle files instead of text responses ...]
      } finally {
        connection.disconnect();
      }
    }
  }

What is going on here? Well, a HTTP connection is opened against the resource on the web that the user wants to access. Depending on configuration, the user can decide to save the response to a file, or in the code that we can see here, just treat it as text. Once the data is read from the web, this thread’s job is done, and it can invoke the user’s event handling block, which runs in the UI thread. It will do so by triggering the GotText method inside a Runnable object, but as you can see, it is run through the activity.runOnUiThread method in order to switch back to the UI thread.
Note that operations such as opening a HTTP connection will take a while and will also block the thread until they are done. That concept of blocking the thread is exactly what we are trying to avoid in the UI thread, but we don’t mind if this other thread gets blocked for as long as it needs. This is the basis of Asynchronous programming as explained in the previous blog post, and we can take advantage of it to give our users a more pleasant experience while using our apps.

Wondering what that AsyncUtil.runAsynchronously method in the Get function is about? Well, these longer tasks are so frequent in App Inventor that there is some supporting code to accomplish them. The class AsyncUtil.java can be used to spawn new threads for the component code. This is the method used in the Web component:

  /**
   * Make an asynchronous call in a separate thread.
   * @param call a {@link Runnable} to run in the thread.
   */
  public static void runAsynchronously(final Runnable call) {
    Thread thread = new Thread(call);
    thread.start();
  }

It’s very simple code; you pass in a Runnable object, and the method creates a thread and starts it. This is the basic threading mechanism in Java. For more information have a look at the Concurrency tutorial.


There are many other examples in the App Inventor sources showing this kind of event-driven approach to longer operations. When you are creating a component, think that any operation that needs to access resources such as the network or external storage, will need to be designed in this way. You might think that, for instance, if you only read small files from storage, then you will be fine doing it in the UI thread. You might even try it, and test it for a bit, and convince yourself that it works fine, but believe me, it will not cut it in the real world. Think about users with slower and older devices, or slow connections to the Internet, or simply think of a device that, at a particular time, might be busy doing some other operation such as upgrading a different app. You really want to get your design correct and functional for all your users out there!