9

Is it possible to return a value after Activity.runOnUiThread() method.

runOnUiThread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int var = SOMETHING;

        // how to return var value.         
    }
});

In this post i see that it's not possible to return a value after Runnable.run() method. But how to use (implement) another interface and return a value after execution.

Hope it's clear for all.

EDIT

May help someone else.

I useD @Zapl's solution, and passED a parameter inside the Callable class constructor, like this :

class MyCallable implements Callable<MyObject> {

        int param;

        public MyCallable (int param) {
            // TODO Auto-generated constructor stub
            this.param = param;
        }

        @Override
        public MyObject call() throws Exception {
            // TODO Auto-generated method stub
            return methodReturningMyObject(this.param);
        }


    }
Community
  • 1
  • 1
S.Thiongane
  • 6,883
  • 3
  • 37
  • 52

3 Answers3

15

If you really want to do it you can use futures and Callable which is roughly a Runnable but with return value.

    final String param1 = "foobar";

    FutureTask<Integer> futureResult = new FutureTask<Integer>(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            int var = param1.hashCode();
            return var;
        }
    });


    runOnUiThread(futureResult);
    // this block until the result is calculated!
    int returnValue = futureResult.get();

This also works for exceptions thrown inside call, they will be re-thrown from get() and you can handle them in the calling thread via

    try {
        int returnValue = futureResult.get();
    } catch (ExecutionException wrappedException) {
        Throwable cause = wrappedException.getCause();
        Log.e("Error", "Call has thrown an exception", cause);
    }
zapl
  • 63,179
  • 10
  • 123
  • 154
  • I needed to pass a parameter in the callable method. I have update the question. Thanks so much – S.Thiongane Jan 28 '14 at 13:27
  • @mansoulx if you rename `int position;` to `int param` you should have a working solution. Otherwise just use a `final` local variable as parameter. Edit: added final var example to answer. – zapl Jan 28 '14 at 13:39
  • `int param` is the variable i used to iterate over a for loop. I don't think a `final` declaration will fit well ... ?! – S.Thiongane Jan 28 '14 at 13:49
  • I don't understand. But `MyCallable` declares that it has a field `position` that is nowhere used and you do `this.param = param;` although there is no field named `param` (e.g. `private int param;` - can be final since nothing is changing that after construction). – zapl Jan 28 '14 at 16:05
  • @mansoulx I'm confused now :) Did you solve your problem using `MyCallable` or is that a question? `final` in a for loop would work like http://pastebin.com/5wGZyTzQ btw – zapl Jan 28 '14 at 16:27
  • Yes it's ok now :). ok your declare new `final index` to take `i` value, ok thank you again. – S.Thiongane Jan 29 '14 at 07:51
  • @zapl `// this block until the result is calculated!` how will it block? the function will wait for UI to complete then continue the code followed? – Felix Aug 30 '16 at 10:51
  • @Fei yes, exactly. – zapl Aug 30 '16 at 11:01
1

The problem there is that you need to handle final variables to be passed to the runOnUiThread() method, and that implies that you cannot modify them inside. However, there is a trick, you can declare a non-primitive data structure prior to the runOnUiThread(), for example a String[] in the case you want to return a String. Of course, you'll need to declare it as final

Once done, in the runOnUiThread() method simply assign the return value you want in yourarray[0], so after you'll be able to access it once you're out the method.

---- EDIT ----

Example:

private void my_method() {
  final String[] your_array = new String[1];

  ...

  runOnUiThread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int var = SOMETHING;

        your_array[0] = "Hello!!!";

        // how to return var value.         
    }
  });

  System.out.println("I've got a message! It says... " + your_array[0]);
}
nKn
  • 13,691
  • 9
  • 45
  • 62
  • thanks for replying. what do you mean by `access it once you're out the method.` : does it mean I can access it just after runOnUiThread instruction ? – S.Thiongane Jan 28 '14 at 13:03
  • I've updated my answer with an example of what I mean, I hope that's what you've been looking for. – nKn Jan 28 '14 at 13:11
  • 2
    That is not guaranteed to work since the thread writing to `your_array[0]` is not guaranteed to be done at that point. You have to wait. And it will in practice pretty much never work. – zapl Jan 28 '14 at 13:14
  • 1
    Correct. This could be combined with a CountDownLatch(1) to synchronize both events (assignation and access). A good example is in the Android reference: http://developer.android.com/reference/java/util/concurrent/CountDownLatch.html – nKn Jan 28 '14 at 13:16
  • 1
    That *might* still be unsafe unless you add some `volatile` or [in case of arrays](http://jeremymanson.blogspot.de/2009/06/volatile-arrays-in-java.html) use e.g. `AtomicIntegerArray`. Not sure if `CountDownLatch` establishes a proper `happens-before` relation. My guess is no. – zapl Jan 28 '14 at 13:21
  • From the reference I understand that using CountDownLatch(1) is intended exactly for this, however, I agree with the rest of your comment. – nKn Jan 28 '14 at 13:25
  • Ok I think my guess is wrong and you don't need volatile on top " actions in a thread prior to calling countDown() happen-before actions following a successful return from a corresponding await() in another thread." from the docs. – zapl Jan 28 '14 at 13:37
  • grazie molte. Un trucco tanto semplice quanto efficace. Grazie. – Nunzio Andolfo Feb 01 '19 at 10:45
1

you can use handler to send message back.

check following example Android: When should I use a Handler() and when should I use a Thread?

Community
  • 1
  • 1
Ketan Parmar
  • 2,962
  • 19
  • 27