Android:使用Lambda间隔执行

时间:2019-04-02 13:00:19

标签: java android lambda

Android中每个X Millis执行代码的方式如下:

    void test(Handler handler) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                // Do something

                // Do it every 200ms
                handler.postDelayed(this, 200);
            }
        });
    }

但是,我已经开始更改代码以尽可能使用lambda。将此模式更改为lambda有一个问题:lambda内部的this引用了外部类,因此不能在postDelayed(...)中使用。

要使其工作,我必须保留对lambda的引用。但是,该引用不能在局部变量中。这意味着为此lambda可运行的对象找到一个有意义的名称,并将其存储为类成员:

    private Runnable intervalRunnable;

    ...

    void testWithLambda() {
        this.intervalRunnable = () -> {
            // Do something

            // Do it every 200ms
            handler.postDelayed(intervalRunnable, 200);
        };
        handler.post(intervalRunnable);
    }

因此,代码更加“现代”,但丑陋且难以维护。

还有另一种解决此问题的方法吗?我喜欢lambda,但我不想在班级上使用这些引用。在这些选项之间,我更喜欢使用匿名类模式。

1 个答案:

答案 0 :(得分:1)

language specification说:

  

15.27.2。 Lambda Body ...   实际上,lambda表达式需要谈论自己(或者自称   递归或调用其其他方法)...如果需要   lambda表达式引用自己(就像通过它),一个方法   引用或匿名内部类代替。

我基本上是说“如果您需要递归lambda,请不要使用lambda。”

基于此,似乎我们在第二个示例中遇到了麻烦,在该示例中,您省去了对类的lambda引用(尽管可以说或多或少地等同于使用方法引用)。

您可以尝试隐藏使用方法引用的事实:

Handler handler = new Handler();

Runnable everyXMillis(Runnable inner, int ms) {
    return () -> {
        inner.run();
        handler.postDelayed(everyXMillis(inner, ms), ms);
    };
}

void testWithMethodReference() {
    handler.post(everyXMillis(() -> {
        // do something
    }, 200));
}

...但是...太糟糕了!如果您担心拥有丑陋且难以维护的代码,似乎最好使用更冗长的匿名Runnable。