Android高级UI面试题汇总(含详细解析 五)

安卓Android面试题汇总——超长15万字总结 本文介绍了Android开发中Activity与Fragment的通信方式,包括接口回调、Bundle传参、Handler、广播、EventBus和ViewModel等6种方法,分析了各自适用场景。接着讲解了Activity四种启动模式(standard、singleTop、singleTask、singleInstance)的特点和应用场景。最后对比了BroadcastReceiver和LocalBroadcastReceiver的区别,指出前者支持跨应用通信但性能较低,后者仅限应用内使用但更高效安全。 阅读详情

Android并发编程高级面试题汇总最全最细面试题讲解持续更新中👊👊
👀你想要的面试题这里都有👀
👇👇👇

如何更新UI,为什么子线程不能更新UI?

这道题想考察什么?

  1. 是否了解为什么子线程不能更新UI的概念与真实场景使用,是否熟悉为什么子线程不能更新UI的本质区别?

考察的知识点

  1. 为什么子线程不能更新UI的概念在项目中使用与基本知识

考生应该如何回答

1.你工作这么些年,有注意到子线程不能更新UI?

答:

其实Android开发者都在说,子线程不能更新UI,难道一定就不能在子线程更新UI吗,那也未必:

下面代码是可以的,运行结果并无异常,可以正常的在子线程中更新了TextView控件

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
        new Thread(new Runnable() {
            @Override
            public void run() {
                tv.setText("Test");
            }
        }).start();
}

但是假如让线程休眠1000ms,就会发生错误:

Only the original thread that created a view hierarchy can touch its views.

上面报错的意思是只有创建视图层次结构的原始线程才能更新这个视图,也就是说只有主线程才有权力去更新UI,其他线程会直接抛异常的;
从at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7905)的异常路径可以看到抛出异常的最终在ViewRootIml的checkThread方法里,ViewRootIml是View的根类,其控制着View的测量、绘制等操作,那么现在我们转到ViewRootImpl.java源码观察:

@Override
public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
}

void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
          "Only the original thread that created a view hierarchy can touch its views.");
        }
}

上面的scheduleTraversals()函数里是对View进行绘制操作,而在绘制之前都会检查当前线程是否为主线程mThread,如果不是主线程,就抛出异常;这样做法就限制了开发者在子线程中更新UI的操作;
但是为什么最开始的在onCreate()里子线程对UI的操作没有报错呢,可以设想一下是因为ViewRootImp此时还没有创建,还未进行当前线程的判断;
现在,我们寻找ViewRootImp在何时创建,从Activity启动过程中寻找源码,通过分析可以查看ActivityThread.java源码,并找到handleResumeActivity方法:

final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume) {
        ···
        // TODO Push resumeArgs into the activity for consideration
        ActivityClientRecord r = performResumeActivity(token, clearHide);
        if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }

            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }
        ···
}

可以看到内部执行了performResumeActivity方法:

public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide) {
	if (r != null && !r.activity.mFinished) { 
        r.activity.performResume(); 
    省略...
} 

会发现在内部调用了Activity的performResume方法,可以肯定应该是要回调生命周期的onResume方法了:

	final void performResume() {
        ···
        mCalled = false;
        // mResumed is set by the instrumentation
        mInstrumentation.callActivityOnResume(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onResume()");
        }
        ···
    }

接着然后又调用了Instrumentation的callActivityOnResume方法:

	public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();
        
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

然后就可以看到执行了 activity.onResume()方法,也就是回调了Activity生命周期的onResume方法;现在让我们回头看看handleResumeActivity方法,会执行这段代码:

···
r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }

发现在内部调用了Activity的makeVisible方法:

void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

源码内部调用了WindowManager的addView方法,而WindowManager方法的实现类是WindowManagerImp类,直接找WindowManagerImp的addView方法:

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }

最终然后又执行了WindowManagerGlobal的addView方法,在该方法中,终于看到了ViewRootImpl的创建;

public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {          
        ···
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
        }
        ···
    }

真相大白:

刚刚源码分析可得知,ViewRootImpl对象是在onResume方法回调之后才创建,那么就说明了为什么在生命周期的onCreate方法里,甚至是onResume方法里都可以实现子线程更新UI,因为此时还没有创建ViewRootImpl对象,并不会进行是否为主线程的判断;

个人理解

必须要在主线程更新UI,实际是为了提高界面的效率和安全性,带来更好的流畅性;你反推一下,假如允许多线程更新UI,但是访问UI是没有加锁的,一旦多线程抢占了资源,那么界面将会乱套更新了,体验效果就不言而喻了;所以在Android中规定必须在主线程更新UI,很合理吧

总结源码分析

第一点:子线程可以在ViewRootImpl还没有创建之前更新UI的

第二点:访问UI是没有加对象锁的,在子线程环境下更新UI,会造成各种未知风险的

第三点:Android开发者一定要在主线程更新UI操作,这个是职业习惯哦

由于面试题内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要2023年Android中高级最全面试真题答案 完整文档的可扫描下方卡片免费获取~

PS:(文末还有使用ChatGPT机器人小福利哦!!大家不要错过)

目录

img

第一章 Java方面

  • Java基础部分
  • Java集合
  • Java多线程
  • Java虚拟机

img

第二章 Android方面

  • Android四大组件相关
  • Android异步任务和消息机制
  • Android UI绘制相关
  • Android性能调优相关
  • Android中的IPC
  • Android系统SDK相关
  • 第三方框架分析
  • 综合技术
  • 数据结构方面
  • 设计模式
  • 计算机网络方面
  • Kotlin方面

img

第三章 音视频开发高频面试题

  • 为什么巨大的原始视频可以编码成很小的视频呢?这其中的技术是什么呢?
  • 怎么做到直播秒开优化?
  • 直方图在图像处理里面最重要的作用是什么?
  • 数字图像滤波有哪些方法?
  • 图像可以提取的特征有哪些?
  • 衡量图像重建好坏的标准有哪些?怎样计算?

img

第四章 Flutter高频面试题

  • Dart部分
  • Flutter部分

img

第五章 算法高频面试题

  • 如何高效寻找素数
  • 如何运用二分查找算法
  • 如何高效解决雨水问题
  • 如何去除有序数组的重复元素
  • 如何高效进行模幂运算
  • 如何寻找最长回文子串

img

第六章 Andrio Framework方面

  • 系统启动流程面试题解析
  • Binder面试题解析
  • Handler面试题解析
  • AMS面试题解析

img

2021年大厂 Android 高级开发面试题汇总(面试题+答案解析) 前言 面试大厂,那就是考察你技术方向的一些专业技能,如果你面试 Android 岗位,那 Android 方向的专业技能就是考察很重要的一个方向。 但是话说回来,即便这条是所有人都知道的共识,也不是所有人都能搞得定。有些人就是觉得自己基础差、非科班,要么知难而退,要么没有决心啃下这块硬骨头,这时候就体现每个人面对困难的方式了。 再退一步讲,即便不想加入大厂,在IT 领域,如果你想吃技术这碗饭,长久来看,专业技能也会制约一个人的上限,等到工作室越长,年龄越来越大,专业技能的熟练程度就会和别的程序员之间差距越. 阅读详情

相关推荐

万达电影 com.wandafilm.app headers check

万达电影 安卓逆向 抓包 逆向 check

weixin_43786514的博客 1438

Android面试题(如何在子线程中做更新UI的操作)

在子线程做更新UI的操作有三种方法:方法一:用Handler 利用Handler 发送消息做更新UI 的操作方法二:用Activity对象的runOnUiThread方法更新 代码如下: new Thread() {              public void run() {                  //完成之后更新UI;                  runOnUiThrea...

gqdbk的博客 511

目标检测数据集 第069期-基于yolo标注格式的玻璃清洁状态检测数据集(含免费分享)

但这类技术的落地,离不开大量标注规范、场景丰富的数据集作为算法训练的支撑,玻璃清洁状态检测数据集的出现,正是为了满足这一市场与技术需求。在高校与科研机构的计算机视觉研究中,该数据集可作为基础研究素材,用于探索物体状态识别的算法优化方向,比如针对玻璃这类透明物体的检测算法改进,或是小样本场景下的状态识别研究。通过摄像头采集车窗、挡风玻璃的图像,算法自动检测玻璃清洁度,若识别到脏污影响视线,及时提醒运维人员清洁,避免因玻璃脏污引发的安全事故,提升交通出行的安全性。

深度学习算法工程师,专注于前沿算法研究与实战应用。在这里,我将分享深度学习领域的实战经验、优质数据集资源以及最新论文解读与精度分析,旨在与广大技术爱好者共同探索人工智能的奥秘,助力技术成长与创新。 128

Android高级UI详解汇总

Android高级UI开发(一)RecyclerView控件的基本使用 Android高级UI开发(二)RecyclerView控件使用----列表项的单击事件、添加(删除)列表项 Android高级UI开发 ( 三 )RecyclerView控件---高级进阶之自己绘制列表分隔线 ...

gaoxiaoweiandy的专栏 4438

私彩视频开奖动画直播源码内部核心技术解析及修改可增加后台操控-持续更新文章!

其实在此很感谢能做出H5开奖系统的码农们,而我本人也喜欢分解此类的东西。 因为特殊原因,该东西本人就不做图片展示,以防他人商业化。 借用开奖摇奖代码首先分解首页index文件。代码如下:(后面持续在原有的作品上添加后台操作) 代码里写的//.....是我的注明代码的所需。 ​ &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;...

yugua3837的博客 5996

英语语法-句法

摘要:本文系统梳理了英语句法知识,重点解析了五种基本句型及其扩展结构。内容包括句子类型(陈述句、疑问句、祈使句、感叹句)、复合句构成(从句分类与连词使用)、特殊句型(倒装、强调、引语转换)等。特别强调句子成分分析技巧,指出每种句子成分可由不同词法单元充当,需掌握成分识别与划分方法。文章还提供了往期语法系列链接,形成完整的英语语法学习体系,帮助读者建立从词法到句法的系统认知框架。

STCNXPARM的博客 8813

Android高级UI面试题汇总(含详细解析 十五)

Android并发编程高级面试题汇总最全最细面试题讲解持续更新中👊👊👀你想要的面试题这里都有👀👇👇👇。

Misdirection_XG的博客 158

Windows 11 的C盘User(用户)文件夹下的用户文件夹名称的修改

背景介绍:由于系统重装导致Windows 11的系统用户名与C盘User(用户)文件夹下的用户名文件夹(公用文件夹旁边的文件夹)出现名称不一致,事例中系统用户名命名为“寂萧”,User(用户)文件夹下的文件夹名称却是“77555”。【QQ邮箱前五位真的真的看着很别扭】注:改名有风险,三思而后行。User(用户)文件夹下的用户名是中文在某些软件的应用场景下产生不便,导致很多软件莫名其妙报错,甚至无法使用,笔者不建议修改为中文名。//和笔者一样的强迫症除外//

2302_79084172的博客 10万+

Android中高级面试题汇总(2021年)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LxOXzNuG-1616402294221)(https://i.loli.net/2020/12/28/hWJbL4ptZUG7anF.png)] 基础篇 Java基础 静态内部类和非静态内部类有什么区别 谈谈你对java多态的理解+java方法的多态性理解 java中接口和继承的区别 线程池的好处+线程池的优点及其原理+线程池的优点 (重点) 为什么不推荐通过Executors直接创建线程池 不怕难之BlockingQue

yundashi168的博客 1万+

复现:Mamba-UNet:降水临近预报的创新解决方案

Mamba-UNet通过其创新的双分支Mamba融合模块、多尺度时空注意力模块和动态分位数加权损失函数,在降水临近预报领域取得了显著的性能提升。它不仅在多种降水场景下表现出色,尤其在预测强降水事件方面展现出了强大的能力。这一创新模型为降水临近预报提供了一种新的解决方案,有望在未来的研究和应用中发挥更大的作用,为应对气候变化带来的挑战提供有力支持。随着技术的不断发展和优化,我们期待Mamba-UNet在更广泛的气象预报任务中发挥更大的价值,为各行各业提供更精准、更可靠的降水预报服务。

hanfeng5268的博客 915

科研级实战】YOLOv11 pose部署至RK3588全流程:让姿态估计模型在边缘端毫秒级运行,我来帮你突破人体行为分析落地壁垒

在智慧安防人体行为分析场景中,基于YOLOv11 pose的模型在云端推理单帧耗时150ms,硬件成本超15000元;经本方案部署到RK3588后,单帧推理耗时降至30ms,硬件成本仅4000元,且关键点检测准确率高达93%以上。在运动姿态评估场景,同款技术路径使模型边缘端推理速度提升6倍,姿态分类精度达95%。这意味着,你也能让自己的姿态估计模型在边缘设备上实现的工业化落地,接下来让我们开启从模型训练到端侧部署的实战征程。

m0_71589036的博客 223

Android高级UI面试题汇总(含详细解析 十六)

Android并发编程高级面试题汇总最全最细面试题讲解持续更新中👊👊👀你想要的面试题这里都有👀👇👇👇。

Misdirection_XG的博客 144

RKNN 端侧部署必看:YOLOv11 Pose 姿态估计模型转换与性能优化实战

随着人工智能技术在边缘计算领域的快速发展,姿态估计作为计算机视觉的重要分支,在智能监控、人机交互、体感游戏等场景中展现出巨大的应用潜力。本文深入研究了YOLOv11 Pose模型在Rockchip RKNN平台上的部署方案,从理论基础、模型转换、平台优化到实际部署进行了全面阐述。通过详细的技术分析和实验验证,证明了RKNN平台能够有效提升YOLOv11 Pose的推理性能,在RK3588硬件平台上实现了高达100 FPS的实时姿态检测,为边缘计算场景下的姿态估计应用提供了高效的解决方案。

m0_71589036的博客 183

超详细!Android 面试题大汇总与深度解析

创建一个继承自 View 或其子类的类:可以直接继承View,也可以根据需求继承TextViewImageView等更具体的子类。例如:java// 后续添加代码定义构造函数:一般需要定义至少两个构造函数,一个是在代码中创建 View 时调用的构造函数,另一个是在 XML 布局中使用时调用的构造函数。如果需要支持自定义属性,还需添加第三个构造函数。例如:java测量 View 的大小:重写方法,通过来确定 View 的宽度和高度。例如:java@Override// 假设默认宽度。

Android开发领域创作者 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android高级UI面试题汇总(含详细解析 十)

Android并发编程高级面试题汇总最全最细面试题讲解持续更新中👊👊👀你想要的面试题这里都有👀👇👇👇。

Misdirection_XG的博客 157

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

2022最新 Android 中高级面试题汇总(含答案解析)

准备面试少不了Android面试题复习,面试题也需要有方法,高效的进行复习,所以给大家分享一份《2022最新 Android 中高级面试题汇总》,基本涵盖了 Android中高级工程师面试必备知识点,希望可以帮助一些想要跳槽涨薪的朋友更好、更高效的复习,实现跳槽涨薪。

datian1234的博客 2826

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Android高级UI面试题汇总(含详细解析 三)

Android并发编程高级面试题汇总最全最细面试题讲解持续更新中👊👊👀你想要的面试题这里都有👀👇👇👇。

Misdirection_XG的博客 224

Android高级UI面试题汇总(含详细解析 十三)

责任链模式是行为型设计模式中的一个。责任链模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

Misdirection_XG的博客 188

【必看】《2024最新Android中高级面试题汇总》它来了~_安卓 中高级

都说三年是程序员的一个坎,能否晋升或者提高自己的核心竞争力,这几年就十分关键。技术发展的这么快,从哪些方面开始学习,才能达到高级工程师水平,最后进阶到Android架构师/技术专家?我总结了这 5大块;我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

2401_84544363的博客 1078

Android高级UI面试题汇总(含详细解析 九)

RequestLayout()方法:会导致调用 onMeasure()方法和 onLayout(),将会根据标志位判断是否 需要 onDraw();onLayout():摆放 viewGroup 里面的子控件,只有自定义ViewGroup需要重写;onDraw():绘制视图本身(ViewGroup 还需要绘制里面的所有子控件);drawChild(): 重新回调每一个子视图的 draw 方法 ,child.draw(canvas, this, drawingTime);

Misdirection_XG的博客 158

Android高级UI面试题汇总(含详细解析 八)

RequestLayout()方法:会导致调用 onMeasure()方法和 onLayout(),将会根据标志位判断是否 需要 onDraw();onLayout():摆放 viewGroup 里面的子控件,只有自定义ViewGroup需要重写;onDraw():绘制视图本身(ViewGroup 还需要绘制里面的所有子控件);drawChild(): 重新回调每一个子视图的 draw 方法 ,child.draw(canvas, this, drawingTime);

Misdirection_XG的博客 174

Android高级UI面试题汇总(含详细解析 一)

View的绘制流程是面试最容易被问到的问题,而且这个问题面试者非常容易满足于一知半解。这道问题的正确的回答方式是从viewRootImpl开始,解析整个viewTree的构建分发流程。由于面试题内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要2023年Android中高级最全面试真题答案 完整文档的可扫描下方卡片免费获取~PS:(文末还有使用ChatGPT机器人小福利哦!!大家不要错过)

Misdirection_XG的博客 185

Android高级UI面试题汇总(含详细解析二十)

名称原理优点适用对象说明浏览器缓存使用HTTP协议头部字段进行缓存控制支持HTTP协议层存储静态资源Android默认实现通过存储键值对实现存储空间大,数据在本地,安全便捷类似Cookies,存储临时的简单数据类似Android中的SP基于SQL利用数据库优势,增删改查方便存储复杂、数据量大的结构化数据不推荐使用,用IndexedDB替代IndexedDB通过存储键值对实现(NoSQL)存储空间大、使用简单灵活存储复杂、数据量大的结构化数据。

Misdirection_XG的博客 177

Android高级UI面试题汇总(含详细解析 七)

享学课堂系列课:高级UI专题:view的绘制流程& WMS专题答疑课。

Misdirection_XG的博客 214

Android详细开发教程,本文章将带你更深入的学习安卓开发

安卓开发是一项充满挑战和乐趣的技能,它可以让你创建各种类型的移动应用,从简单的工具到复杂的游戏,本文章将为你提供一个详细的学习路线,参考内容,应用场景,实用案例及代码示例,以及一些优秀的GitHub开源项目,帮助你深入掌握安卓开发!

HSX的博客 4720
上一篇: Android高级UI面试题汇总(含详细解析 四)
下一篇: Android高级UI面试题汇总(含详细解析 六)
网络安全-XG
博客等级 码龄5年 1万+粉丝 2752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值