how can I pass a variable into a new Runnable declaration?

Jimmy picture Jimmy · Nov 28, 2010 · Viewed 27.5k times · Source

I have the following :

Runnable done = new Runnable()
    {
        public void run()
        {
            System.out.println("Hello");
        }
    };

And then in my Android activity I'll call something like :

runOnUIThread(done);

Which I then call. However, I want that "Hello" not to be hardcoded, so I can pass it in. Otherwise I'll have to have one of these declarations for every String I want to print.

(This is actually an android question, but slimmed it down to basic Java so its easier to answer)

Thanks

Answer

Ralph picture Ralph · Nov 28, 2010

In Java (and I believe it is the same in Android too), you can use a anonymous inner class, like suggested by Bart van Heukelom. This solution has the advantage that have to write less code, and you could access fields and methods ouf the outer class.

But it has 2 drawbacks:

  • the variable "hello" has to be final,

  • the anonymous class has a internal reference to the outer class instance - this means the outer class being retained when it would otherwise be eligible for garbage collection. @See: Effective Java [Joshua Bloch], Item 22: Favor static member classes over nonstatic

And in my humble opinion, it is bad practice to parametrize a class instance in this way.

So I believe, as long as you do not need to access methods and fields of the outer class, it is better to write an specific class for this task and make it a static member class.

class Demo {
...

  private static class MyRunnable implements Runnable {
     private final String message;

     MyRunnable(final String message) {
       this.message = message;
     }

     public void run() {
       System.out.println(message);
     }
  }

  public void startThread() {
    MyRunnable myRunnable = new MyRunnable("Hello");

    runOnUIThread(myRunnable); 
  }
...
}