6

My reading of the android documentation finds the methods forceLayout() (which is to produce a layout display at the next layout request) and requestLayout() (which is supposed to post an immediate layout request), but I can not get them to behave as advertised. In particular, if I do one set text before a Thread.Sleep and one after, it waits for the Sleep to finish before setting both texts at once, whether or I call the forceLayout() and requestLayout() in between. Please do not respond with a lot of nonsense about how I should not call a Thread.Sleep in the UI thread. If I wrap the Thread.Sleep in a CountDownTimer it works perfectly well (as long as I have the tick time short enough to not interfere with sleep time, and the duration of the timer long enough to permit the Sleep to finish. The following is an example:

    int i=0;
TextView tv2;
TextView tv1;
LinearLayout ll;
Button bt;
@Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ll=new LinearLayout(this);
    ll.setOrientation(LinearLayout.VERTICAL);
    tv1=new TextView(this);
    tv2=new TextView(this);
    bt=new Button(this);
    bt.setText("Press to start");
    ll.addView(bt);
    ll.addView(tv1);
    ll.addView(tv2);
    tv2.setText("");
    setContentView(ll);
    bt.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            tv1.setText("starting sleep");
            new CountDownTimer(6000,50){
              public void onTick(long msuf)
                {if(i==1)
                    {
                try{
              Thread.sleep(4000);
              tv2.setText("waking up");
               }
            catch(InterruptedException e){};
            }
                i++;
                 }
               public void onFinish(){}}.start();
              }         
      });

        }
Jordan Miner
  • 2,034
  • 17
  • 19
peter gottlieb
  • 441
  • 2
  • 5
  • 9
  • See also http://stackoverflow.com/questions/13856180/usage-of-forcelayout-requestlayout-and-invalidate – Suragch Feb 24 '17 at 04:22

1 Answers1

11

[lots of nonsense about calling sleep() in UI thread]. If i get it right, you mean having something like:

//...inside onTick()
try {
    tv2.setText("almost waking up"); // first setText()
    Thread.sleep(4000);
    tv2.setText("waking up"); // second seText()
}

If you make your main thread sleep, it will just stop processing anything: the current method, the thread loop and the message queue. Once awake again, it will finish executing the method, with the second setText() overriding the first one, and then leave the thread loop continue and do the UI refresh, showing only the second text.

Not requestLayout() nor forceLayout() can actually make the UI refresh immediately, they will both schedule a layout request in the thread loop. I'm not sure, but I think the difference between them is that requestLayout() is called by a view that has changed its size/position in its parent, and forceLayout() is called by a ViewGroup that needs its children to be re-laid out.

Therefore [more nonsense about calling sleep() in UI thread]. For such things calling postDelayed() on a main thread handler is the best solution probably, if you don't want to mess with multithreading.

bigstones
  • 15,087
  • 7
  • 65
  • 82
  • Do you have an advice how I can force my layout (everything) to redraw? I have an issue where I toggle the visibility of a VideoView which works but the result is not visible (but touchable, so I know the VideoView is there or not...) – WarrenFaith Mar 25 '11 at 10:00
  • @WarrenFaith I can't think of anything else than calling `requestLayout()` or `invalidate()` on the root of your layout. I would think it's a `VideoView` issue though. Have you tried with both `GONE` and `INVISIBLE`? – bigstones Mar 25 '11 at 10:17
  • yes and no changes. If I start with visible and try do make it gone, it only goes away when I have something like a dialog pop up. The same when starting with invisible – WarrenFaith Mar 25 '11 at 10:30