【问题标题】:return a value after Activity.runOnUiThread() method在 Activity.runOnUiThread() 方法之后返回一个值
【发布时间】:2014-02-19 18:46:39
【问题描述】:

Activity.runOnUiThread() 方法后是否可以返回值。

runOnUiThread(new Runnable() {

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

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

在这个post 中,我看到在Runnable.run() 方法之后无法返回值。但是如何使用(实现)另一个接口并在执行后返回一个值。

希望大家都清楚。

编辑

可以帮助别人。

我使用了@Zapl 的解决方案,并在Callable 类构造函数中传递了一个参数,如下所示:

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);
        }


    }

【问题讨论】:

    标签: android interface runnable


    【解决方案1】:

    如果你真的想这样做,你可以使用期货和Callable,这大致是Runnable,但有返回值。

        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();
    

    这也适用于call 内部抛出的异常,它们将从get() 重新抛出,您可以在调用线程中通过

        try {
            int returnValue = futureResult.get();
        } catch (ExecutionException wrappedException) {
            Throwable cause = wrappedException.getCause();
            Log.e("Error", "Call has thrown an exception", cause);
        }
    

    【讨论】:

    • 我需要在可调用方法中传递一个参数。我已经更新了这个问题。非常感谢
    • @mansoulx 如果您将int position; 重命名为int param,您应该有一个可行的解决方案。否则,只需使用 final 局部变量作为参数。编辑:添加了最终的 var 示例来回答。
    • int param 是我用来遍历 for 循环的变量。我认为final 声明不太合适...?!
    • 我不明白。但是MyCallable 声明它有一个字段position 是无处使用的,您可以使用this.param = param; 尽管没有名为param 的字段(例如private int param; - 可以是最终的,因为在构造之后没有任何改变)。
    • @mansoulx 我现在很困惑 :) 您是否使用 MyCallable 解决了您的问题,或者这是一个问题? final 在 for 循环中的工作方式类似于 pastebin.com/5wGZyTzQ btw
    【解决方案2】:

    您可以使用处理程序发回消息。

    检查以下示例 Android: When should I use a Handler() and when should I use a Thread?

    【讨论】:

      【解决方案3】:

      问题在于您需要处理要传递给runOnUiThread() 方法的final 变量,这意味着您不能在内部修改它们。但是,有一个技巧,您可以在runOnUiThread() 之前声明一个非原始数据结构,例如在您想要返回String 的情况下使用String[]。当然,您需要将其声明为final

      完成后,在runOnUiThread() 方法中只需在yourarray[0] 中分配您想要的返回值,这样您就可以在退出该方法后访问它。

      ---- 编辑----

      例子:

      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]);
      }
      

      【讨论】:

      • 感谢您的回复。 access it once you're out the method. 是什么意思:这是否意味着我可以在 runOnUiThread 指令之后访问它?
      • 我已经用我的意思的一个例子更新了我的答案,我希望这就是你一直在寻找的。​​span>
      • 这不能保证工作,因为写入your_array[0] 的线程不能保证在那时完成。你得等一等。而且它在实践中几乎不会奏效。
      • 正确。这可以与 CountDownLatch(1) 结合使用以同步两个事件(分配和访问)。 Android 参考中有一个很好的例子:developer.android.com/reference/java/util/concurrent/…
      • 可能 仍然不安全,除非您添加一些 volatilein case of arrays 使用例如AtomicIntegerArray。不确定CountDownLatch 是否建立了正确的happens-before 关系。我的猜测是没有。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-27
      • 1970-01-01
      • 2017-10-01
      • 2020-07-12
      • 2013-11-06
      • 2021-07-07
      • 1970-01-01
      相关资源
      最近更新 更多