Damn Vegetables
Damn Vegetables

Reputation: 12464

Kotlin anonymous class this

I am using the sample code in this question(getWidth() and getHeight() of View returns 0).

It had the following code,

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                view.getHeight(); //height is ready
            }
        });

And I wrote it in Kotlin like this

image_view.viewTreeObserver.addOnGlobalLayoutListener{
    image_view.viewTreeObserver.removeOnGlobalLayoutListener { this }
    Log.d("Should be called once", "Height = " + image_view.height + ", Width = " + image_view.width)
};

The result was,

11-22 19:18:33.319 4754-4754/loser.qrcode D/Should be called once: Height = 672, Width = 672
11-22 19:18:33.328 4754-4754/loser.qrcode D/Should be called once: Height = 672, Width = 672

So, it was called twice. That is, removeOnGlobalLayoutListener did not work. What should I use instead of this?

Upvotes: 1

Views: 1438

Answers (1)

crgarridos
crgarridos

Reputation: 9263

The problem here is that Kotlin is asumming removeOnGlobalLayoutListener will need a SAM expression. Then when you are passing { this }, you are just creating another OnGlobalLayoutListenerinstance, here the equivalent:

view.getViewTreeObserver().removeOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        YourOuterClass.this;
    }
});

And this listener doesn't exist in the current listeners list

In order to solve this, you have to declare your OnGlobalLayoutListener as an object and not as a lamba, like this you can reference the correct "this" and remove the listener properly once is called.

image_view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
    override fun onGlobalLayout() {
        image_view.viewTreeObserver.removeOnGlobalLayoutListener(this)
        Log.d("Should be called once", "Height = " + image_view.height + ", Width = " + image_view.width)
    }
})

Upvotes: 1

Related Questions