从另一个线程更新UI中的View.GONE与View.INVISIBLE

时间:2019-02-06 09:53:18

标签: android

我从另一个线程使用了setVisibility(View.INVISIBLE),视图消失了,但是当我使用View.GONE时,应用程序因错误而崩溃:

  

只有创建视图层次结构的原始线程才能触摸其   视图。

setVisibility(View.INVISIBLE)setVisibility(View.GONE);都在更新UI线程时有什么区别?

        final Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            progressBar.setVisibility(View.INVISIBLE);
            textView.setVisibility(View.GONE);
        }
    });

更新

我知道INVISIBLEGONE之间的区别。我的意思是为什么INVISIBLE也不例外,同时它也会触及其他线程中的UI元素。

3 个答案:

答案 0 :(得分:1)

您只能通过UI线程更改布局,并说import datetime result = [{'start_date': datetime.date(2019, 1, 20)}, {'start_date': datetime.date(2019, 1, 21)}, {'start_date': datetime.date(2019, 1, 22)}] # Map function res = map(lambda d: str(d['start_date']), result) print(res) # List-comprehension res = [ str(d['start_date']) for d in result ] print(res) 不会对视图的结构进行任何更改,因为View.INVISIBLE在那里。在View释放空间的同时,释放已使用的空间,这是层次结构的变化。

您可以使用runOnUiThread对其进行修复。

答案 1 :(得分:1)

docs

  

不可见:此视图不可见,但仍占用空间   布局目的。与setVisibility(int)和android:visibility一起使用。

     

已消失:此视图是不可见的,并且不占用任何空间   布局目的。与setVisibility(int)和android:visibility一起使用。

因此,如果您使用不可见的标记视图,则将被隐藏,但是它所占据的空间将在那里,如果您使用了消失的标记视图,则将被隐藏,并且它所占据的空间将消失。

此外,您正在从主线程之外的其他线程更改视图,因为主线程是唯一可以与ui元素进行交互的线程,所以这是不允许的。

答案 2 :(得分:0)

在一个案例中,这个问题对我来说似乎很合理。如果您运行以下代码:-

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);
    button=findViewById(R.id.btn1);
    new Thread(new Runnable() {
        @Override
        public void run() {
            button.setVisibility(View.INVISIBLE);
            Log.e("thread",Thread.currentThread().getName());
        }
    }).start();
}

它运行无误,并将Button的可见性设置为INVISIBLE。对于VISIBLE和调用视图的任何其他操作,它将运行类似。

new Thread(new Runnable() {
        @Override
        public void run() {
            Log.e("thread",Thread.currentThread().getName());
            button.setText("Hi from "+Thread.currentThread().getName());

        }
    }).start();

这也将运行。是的,它确实将当前线程打印为新线程:-E/thread: Thread-16
我认为原因是View#post()。 View在屏幕上绘制后应执行的任何操作。在这种情况下,现在绘制了View,这就是为什么当前操作将推入主线程处理程序的消息队列的原因。它将在绘制完成后运行(由于View#post()而在主线程上运行)而没有任何错误。

另一方面,如果在某个事件上调用此函数,则单击按钮单击会抛出Exception,因为视图已绘制,并且它将直接在同一线程上调用该操作,而无需通过Handler发布

希望我已经说得足够清楚了。如果这个理论无论如何是对的,请纠正我。