Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android global layout listener called repeatedly in android

Add global layout listener gets called even if there is no listener attached, It gets in a loop in this situation, how can I edit attributes without firing global layout listener in a loop ? thank you

final View getDecorView = activity.getWindow().getDecorView();
            getDecorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {

                    if (Build.VERSION.SDK_INT > 16) {
                        getDecorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        getDecorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }

                    final TextView textView3 = (TextView) decorView.findViewById(2131558456);
                    if (textView3 != null) {
                                textView3.setText("updated");                      textView3.setBackgroundColor(Color.parseColor("#444444"));
                    }

                    getDecorView.getViewTreeObserver().addOnGlobalLayoutListener(this);

                }
            });
like image 856
Mike Avatar asked May 09 '16 12:05

Mike


1 Answers

This sort of solves your problem:

final View decorView = activity.getWindow().getDecorView();
final TextView textView3 = (TextView) decorView.findViewById(2131558456);
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        if (Build.VERSION.SDK_INT > 16) {
            decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        } else {
            decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }


        if (textView3 != null && !textView3.getText().equals("updated")) {
            textView3.setText("updated");
            textView3.setBackgroundColor(Color.parseColor("#444444"));
        }

        decorView.getViewTreeObserver().addOnGlobalLayoutListener(this);

    }
});

I'm assuming that textview3 doesn't originally have text equal to "updated", so when you set its text to "updated", it acts as a sort of flag, so that you don't set it again in the future. You could also do the following, which IMHO is a bit cleaner because you have an actual boolean flag representing whether you should update the TextView or not.

final View decorView = activity.getWindow().getDecorView();
final TextView textView3 = (TextView) decorView.findViewById(2131558456);
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

    boolean updateTextview = true;

    @Override
    public void onGlobalLayout() {

        if (Build.VERSION.SDK_INT > 16) {
            decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        } else {
            decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }


        if (textView3 != null && updateTextview) {
            updateTextview = false;
            textView3.setText("updated");
            textView3.setBackgroundColor(Color.parseColor("#444444"));
        }

        decorView.getViewTreeObserver().addOnGlobalLayoutListener(this);

    }
});

Both solutions should work, because they stop the constant updating of textview3, which leads to another layout pass which leads to the updating of textview3 which leads to another layout pass which leads... on and on.

like image 178
roarster Avatar answered Oct 06 '22 01:10

roarster