Roughly speaking on the screen we have 2 views. When clicking on each of them, a certain resource-intensive code is executed, a part of which is processed in threads (execution time is about 1 second). The trouble is that when you click, the view should immediately disappear from the screen, but the deactivation occurs only after the onClick method completes. It turns out like a hang, it suits me, it does not suit only that the view does not disappear right away. Logs showed that the property is being set, but for some reason the screen is not updated. Put invalidate (), but it did not bring success. What am I doing wrong? Logs:

view is visible true view is visible false //задержка примерно секунда, вью видна onClick is finished //вью исчезает с экрана 

Code:

  private class OnClicker implements OnClickListener { @Override public void onClick(View view) { Logger.d("view is visible", view.getVisibility() == View.VISIBLE); view.setVisibility(View.INVISIBLE); view.invalidate(); Logger.d("view is visible", _listMenu.getVisibility() == View.VISIBLE); switch (view.getId()) { case R.id.view1: run1(); break; case R.id.view2: run2(); break; } Logger.d("onClick is finished"); } } 
  • one
    Show what are run1 or run2, at least in general terms. One gets the persistent feeling that they are still executed in the UI stream, despite the fact that at the beginning of the post you state something else. - falstaf
  • I understand correctly that run1 run2 methods run for about 1 second? - KoVadim
  • falstaf, there is a work with the base. That's not the point. Even if subsequent actions are not in threads. As I understand it, the view should be updated before one of these methods is called. KoVadim yes. - st_er
  • until the onClick method completes, nothing will be updated. Take out the code in AsyncTask. Crutches, like Delf Application.ProcessMessages; I did not see. If your code will be executed for more than 5 seconds - get ANR - the application does not respond + a bunch of thoughts from users. - KoVadim
  • it only queues the update request. And it will execute it only on an output from the current method. - KoVadim

1 answer 1

View.setVisibility only updates the view flags and, if necessary, the background drawable (Drawable.setVisible) flags background drawable (Drawable.setVisible) . Nothing more. At the next iteration of rendering, these flag changes will be taken into account, but you will not release the UI stream for this, therefore, all changes will take effect only after the end of run1/run2 .

  • I thought this is resolved view.invalidate (); - st_er
  • View.invalidate ultimately boils down to calls to ViewParent.invalidateChild () and companion, which, in turn, mark the specified area as dirty. requiring redrawing. The actual update of this area will occur a little later, or rather, in the render loop, when you release the UI stream. - falstaf
  • it will help, but public void postInvalidate (), and you need to use it from another thread, like a scool - Gorets
  • Thanks to everyone, I will deal with the code in the threads then. - st_er
  • View.postInvalidate () will only send the desired message to the Handler of the stream, and it will parse the message and process it again, when it reaches the queue. That is, in this case, when run1 / run2 execution ends. The only correct solution is to not delay the UI stream under any circumstances. Otherwise - the trouble with responsiveness, usability and, as a result, the average score in GooglePlay. - falstaf