ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android 非UI线程不能更新UI

2021-08-28 19:33:51  阅读:203  来源: 互联网

标签:args ActivityThread 更新 线程 Looper UI Android


1. 什么是UI线程?

   App通过Zygote fork创建一个App进程,通过ActivityThread的main()函数创建ActivityThread实例及UI线程Looper对象。

  程序都有一个main()函数,也就是主函数,Android中的主函数在ActivityThread这个类中,主函数是一个静态方法。

  源码:

public class ActivityThread {
    ...

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    
    ....  
}

  上面代码和创建一个工作线程及创建工作线程的Looper代码是一样的。

  UI线程就是通过AMS Zygeto fork创建进程时创建的线程主线程就是UI线程。

2. 主线程是如何工作的?

  就是Handler原理,典型的生产者消费者模式;

 

 

 

 

3. 假设,把UI线程设计成线程安全的?

  1. 什么是线程不安全?

  可变资源(内存)线程间共享。

  2. 如果多线程更新TextView,线程安全就是设计成这样:

 

 

  图上可知就是加锁,加锁是比较耗时的,但是,UI更新又是一个高频更新。

  3. 为什么不设计成线程安全?

    1. UI具有可变性,甚至是高频可变性;

    2. UI对响应时间敏感性的要求UI操作必须高效;

    3. UI组件必须批量绘制来保住效率;

4. 非UI线程就一定不能更新UI吗?

  1. 工作线程间接更新UI,比如:网络请求:

  正常通知UI线程更新UI:

 

 

  工作线程(I/O线程)间接更新UI:

 

 

 

  2. 工作线程直接更新UI,比如:SurfaceView就是子线程更新渲染的:

 

 

 

  视频画面渲染显示就是使用SurfaceView。

  地图使用的是GLSurfaceView,是SurfaceView子类,GLSurfaceView是OpenGL渲染。

 

标签:args,ActivityThread,更新,线程,Looper,UI,Android
来源: https://www.cnblogs.com/naray/p/13035205.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有