在Android中,非主线程不能更新UI

本文探讨了Android中非主线程不能更新UI的原因,并通过实例测试解释了为何在子线程中直接操作UI会导致应用崩溃。文章详细分析了Handler、WindowManager和ViewRootImpl的角色,以及如何在子线程中安全地更新UI。此外,还讨论了requestLayout()与invalidate()的区别以及可能的遗留问题。
摘要由CSDN通过智能技术生成

上一篇文章《Anroid异步消息机制(Handler、Looper、Message、MessageQueue)以及ThreadLocal运用》提到,Android中,非主线程不能更新UI(ViewRootImpl在主线程中创建,所以我们要在主线程中更新UI。同理,如果ViewRootImpl在子线程中创建的话,那么也可以在子线程中更新UI,也就是说在哪里更新UI和ViewRootImpl在哪里创建是关联的。默认ViewRootImpl在主线程中创建),这时候我们可以借助Handler来实现(Activiy.runOnUiThread()也可以实现,但原理也是Handler,调用的post(Runnable))“。

一、我们做个测试

1、activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/main_thread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="UI主线程" />

    <TextView
        android:id="@+id/sub_thread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="UI主线程中直接建立子线程" />

    <TextView
        android:id="@+id/sub_thread_thread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="UI主线程中直接建立子线程的子线程" />
    
    <TextView
        android:id="@+id/click_window"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="直接更新UI线程" />
    
    <TextView
        android:id="@+id/click_subclass_window"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="直接建立子类更新UI线程并且跳出子窗口" />
    
    <TextView
        android:id="@+id/click_thread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,直接建立子线程" />
    
    <TextView
        android:id="@+id/click_subclass_thread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,建立子类,子类中建立子线程" />
      
    <Button
        android:id="@+id/click_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,直接更新UI线程" />
    <Button
        android:id="@+id/click_subclass_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,直接建立子类更新UI线程并且跳出子窗口" />
    <Button
        android:id="@+id/click_thread_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,直接建立子线程" />   
        
    <Button
        android:id="@+id/click_subclass_thread_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,建立子类,子类中建立子线程" />
    
    <Button
        android:id="@+id/click_windowManager_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击,建立子窗口" />

</LinearLayout>

2、MainActivity.java

import android.os.Bundle;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextV
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值