更新带参数的Runnable中的UI

huangapple go评论75阅读模式
英文:

Updating UI from Runnable with parameters

问题

我在Stackoverflow上找到了多种方法来做这件事,但仍然没有找到一个使用参数的好方法。在我的情况下,我有一个线程,需要不断地使用日志信息更新UI主线程(我没有使用Asynctask;我正在实现Google Maps的TileProvider接口)。

以下是我在线程中运行的代码,它能够正常工作:

Handler mainHandler = new Handler(Looper.getMainLooper());
...

public void debugMsg(final String msg)
{
   Runnable myRunnable = (new Runnable()
   {
     @Override
     public void run()
     {
        Log.Add(msg); // 在主线程中更新UI的静态函数
     }
   });

  mainHandler.post(myRunnable);
}

问题是,如果我理解正确,每次调用debugMsg时,它都会实例化一个新的Runnable对象。我认为这不是一个很好的做法,特别是因为它会频繁地进行,所以我想知道是否有一种方法可以在我的线程内重用该runnable。或者也许有更好的做法...

英文:

I found multiple options to do that on Stackoverflow, but still haven't found a good way to do it with parameters. In my case, I have a thread that continuously needs to update the UI main thread with logging information (I'm not using Asynctask; I'm implementing TileProvider interface from Google Maps)

This is what I have that runs in my thread and it works:

Handler mainHandler = new Handler(Looper.getMainLooper());
...

public void debugMsg(final String msg)
{
   Runnable myRunnable = (new Runnable()
   {
     @Override
     public void run()
     {
        Log.Add(msg); // static function that update the UI in the main thread
     }
   });
 
  mainHandler.post(myRunnable);
}

Problem is that if I understand correctly, every time I call debugMsg, it is going to instantiate a new Runnable object. I don't think that's a very good practice especially because it's going to be heavily done, so I would like to know if there is way to reuse that runnable inside my thread. Or maybe there's a better way of doing it...

答案1

得分: 1

如果您想要重用Runnable,可以将其简单地存储为成员变量。

private Runnable myRunnable = new Runnable() {
    @Override
    public void run() { ... };
};

您可能会想,在需要参数的情况下,可以使用Consumer

private Consumer<String> myConsumer = (str) -> { Log.d("tag", str); };

然后在debugMsg中:

mainHandler.post(() -> { myConsumer.accept(msg); });

然而,您的Lambda表达式仍然会成为每次运行debugMsg时实例化的函数式接口对象。但主要逻辑不会被重新创建,myConsumer将被重用。

更新:

您可以自己实现Runnable接口,类似于以下内容:

public abstract class ParameterisedRunnable implements Runnable {
    
    public String param = "";

    public void setParam(String str) {
        param = str;
    }
}

然后像普通的Runnable一样创建ParameterisedRunnable的实例(重写run方法)。

private ParameterisedRunnable myRunnable = new ParameterisedRunnable() {
    @Override
    public void run() {
        Log.d("tag", param);
    }
};

您可以像这样使用它:

myRunnable.setParam(msg);
mainHandler.post(myRunnable);
英文:

If you want to reuse the Runnable, you can easily store it as a member variable.

private Runnable myRunnable = new Runnable() {
    @Override
    public void run() { ... };
}

You might think, in case of having parameter, you can use consumer.

private Consumer&lt;String&gt; myConsumer = (str) - &gt; { Log.d(&quot;tag&quot;, str); };

And then in debugMsg

mainHandler.post(() -&gt; { myConsumer.accept(msg); });

However, your lambda still will be an object of functional interface instantiated every time you run debugMsg. But the main logic will not be recreated and myConsumer will be reused.

UPD:

You can implement Runnable interface yourself, something like

public abstract class ParameterisedRunnable implements Runnable {
    
    public String param = &quot;&quot;;

    public void setParam(String str) {
        param = str;
    }
}

And then just create the instance of ParameterisedRunnable like the regular Runnable (overriding run method).

private ParameterisedRunnable myRunnable = new ParameterisedRunnable() {
    @Override
    public void run() {
        Log.d(&quot;tag&quot;, param);
    }
}

You will able to use it like that.

myRunnable.setParam(msg);
mainHandler.post(myRunnable);

huangapple
  • 本文由 发表于 2020年8月22日 23:04:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63537659.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定