最全Android面试大纲(二)【含答案】

Android优化工具

TraceView

raceview 是Android SDK中自带的一个工具,可以 对应用中方法调用耗时进行统计分析,是Android性能优化和分析时一个很重要的工具。使用方法:第一种是在相应进行traceview分析的开始位置和结束位置分别调用startMethodTracing和stopMethodTracing方法。第二种是在ddms中直接使用,即在ddms中在选中某个要进行监控的进程后,点击如图所示的小图标开始监控,在监控结束时再次点击小图标,ddms会自动打开traceview视图。

Systrace

Systrace是Android4.1中新增的性能数据采样和分析工具。它可帮助开发者收集Android关键子系统(如surfaceflinger、WindowManagerService等Framework部分关键模块、服务)的运行信息,从而帮助开发者更直观的分析系统瓶颈,改进性能。

Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载以及Android各个子系统的运行状况等。

Dalvik与ART的区别?

Dalvik是Google公司自己设计用于Android平台的Java虚拟机。Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一,它可以支持已转换为.dex(即Dalvik Executable)格式的Java应用程序的运行,.dex格式是专为Dalvik应用设计的一种压缩格式,适合内存和处理器速度有限的系统。Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为独立的Linux进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。

ART代表Android Runtime,其处理应用程序执行的方式完全不同于Dalvik,Dalvik是依靠一个Just-In-Time(JIT)编译器去解释字节码。开发者编译后的应用代码需要通过一个解释器在用户的设备上运行,这一机制并不高效,但让应用能更容易在不同硬件和架构上运行。ART则完全改变了这套做法,在应用安装的时候就预编译字节码到机器语言,这一机制叫 Ahead-Of-Time(AOT) 编译 。在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。

ART优点:
  1. 系统性能的显著提升
  2. 应用启动更快、运行更快、体验更流畅、触感反馈更及时
  3. 更长的电池续航能力
    4.支持更低的硬件
ART缺点:
  1. 更大的存储空间占用,可能会增加10%-20%
  2. 更长的应用安装时间

Android动态权限?

Android 6.0 动态权限,这里以拨打电话的权限为例,首先需要在Manifest里添加android.permission.CALL_PHONE权限。

int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
    if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
                this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CODE_ASK_CALL_PHONE);
        return;
    }
    ```
    在获取权限后,可以重写Activity.onRequestPermissionsResult方法来进行回调。
    ```
    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_CALL_PHONE:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted
                Toast.makeText(MainActivity.this, "CALL_PHONE Granted", Toast.LENGTH_SHORT)
                        .show();
            } else {
                // Permission Denied
                Toast.makeText(MainActivity.this, "CALL_PHONE Denied", Toast.LENGTH_SHORT)
                        .show();
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

ViewPager如何判断左右滑动?

实现OnPageChangeListener并重写onPageScrolled方法,通过参数进行判断。

ListView与RecyclerView

  1. ViewHolder:在ListView中,ViewHolder需要自己来定义,且这只是一种推荐的使用方式,不使用当然也可以,这不是必须的。而在RecyclerView中使用 RecyclerView.ViewHolder 则变成了必须,尽管实现起来稍显复杂,但它却解决了ListView面临的上述不使用自定义ViewHolder时所面临的问题。

  2. LayoutManager:RecyclerView提供了更加丰富的布局管理。LinearLayoutManager,可以支持水平和竖直方向上滚动的列表。StaggeredGridLayoutManager,可以支持交叉网格风格的列表,类似于瀑布流或者Pinterest。GridLayoutManager,支持网格展示,可以水平或者竖直滚动,如展示图片的画廊。

  3. ItemAnimator:相比较于ListView,RecyclerView.ItemAnimator 则被提供用于在RecyclerView添加、删除或移动item时处理动画效果。

  4. ItemDecoration:RecyclerView在默认情况下并不在item之间展示间隔符。如果你想要添加间隔符,你必须使用RecyclerView.ItemDecoration类来实现。

ListView可以设置选择模式,并添加MultiChoiceModeListener,RecyclerView中并没有提供这样功能。

SpannableString

TextView通常用来显示普通文本,但是有时候需要对其中某些文本进行样式、事件方面的设置。Android系统通过SpannableString类来对指定文本进行相关处理。可以通过SpannableString来对TextView进行富文本设置,包括但不限于文本颜色,删除线,图片,超链接,字体样式

描述一下Android手机启动过程和App启动过程?

Android手机启动过程

当我们开机时,首先是启动Linux内核,在Linux内核中首先启动的是init进程,这个进程会去读取配置文件system\core\rootdir\init.rc配置文件,这个文件中配置了Android系统中第一个进程Zygote进程。

启动Zygote进程 –> 创建AppRuntime(Android运行环境) –> 启动虚拟机 –> 在虚拟机中注册JNI方法 –> 初始化进程通信使用的Socket(用于接收AMS的请求) –> 启动系统服务进程 –> 初始化时区、键盘布局等通用信息 –> 启动Binder线程池 –> 初始化系统服务(包括PMS,AMS等等) –> 启动Launcher

App启动过程

《最全Android面试大纲(二)【含答案】》 在这里插入图片描述

  1. 应用的启动是从其他应用调用startActivity开始的。通过代理请求AMS启动Activity。

  2. AMS创建进程,并进入ActivityThread的main入口。在main入口,主线程初始化,并loop起来。主线程初始化,主要是实例化ActivityThread和ApplicationThread,以及MainLooper的创建。ActivityThread和ApplicationThread实例用于与AMS进程通信。

  3. 应用进程将实例化的ApplicationThread,Binder传递给AMS,这样AMS就可以通过代理对应用进程进行访问。

  4. AMS通过代理,请求启动Activity。ApplicationThread通知主线程执行该请求。然后,ActivityThread执行Activity的启动。

  5. Activity的启动包括,Activity的实例化,Application的实例化,以及Activity的启动流程:create、start、resume。

可以看到 入口Activity其实是先于Application实例化,只是onCreate之类的流程,先于Activity的流程。另外需要scheduleLaunchActivity,在ApplicationThreaad中,对应AMS管理Activity生命周期的方法都以scheduleXXXActivity,ApplicationThread在Binder线程中,它会向主线程发送消息,ActivityThread的Handler会调用相应的handleXXXActivity方法,然后会执行performXXXActivity方法,最终调用Activity的onXXX方法

Include、Merge、ViewStub的作用

Include:布局重用
  • <include />标签可以使用单独的layout属性,这个也是必须使用的。

  • 可以使用其他属性。<include />标签若指定了ID属性,而你的layout也定义了ID,则你的layout的ID会被覆盖,解决方案。

  • 在<include />标签中所有的android:layout_*都是有效的,前提是必须要写layout_width和layout_height两个属性。

  • 布局中可以包含两个相同的include标签

Merge:减少视图层级,多用于替换FrameLayout或者当一个布局包含另一个时,<merge/>标签消除视图层次结构中多余的视图组。

例如:你的主布局文件是垂直布局,引入了一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,使用的话反而减慢你的UI表现。这时可以使用标签优化。

ViewStub:需要时使用。优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。需要使用时调用inflate()。

Asset目录与res目录的区别

  • assets 目录:不会在R.java文件下生成相应的标记,assets文件夹可以自己创建文件夹,必须使用AssetsManager类进行访问,存放到这里的资源在运行打包的时候都会打入程序安装包中,

  • res 目录:会在R.java文件下生成标记,这里的资源会在运行打包操作的时候判断哪些被使用到了,没有被使用到的文件资源是不会打包到安装包中的。

res/raw 和 assets文件夹来存放不需要系统编译成二进制的文件,例如字体文件等

res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹

System.gc && Runtime.gc

System.gc和Runtime.gc是等效的,在System.gc内部也是调用的Runtime.gc。调用两者都是通知虚拟机要进行gc,但是否立即回收还是延迟回收由JVM决定。两者唯一的区别就是一个是类方法,一个是实例方法。

Application 在多进程下会多次调用 onCreate() 么?

当采用多进程的时候,比如下面的Service 配置:

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="false"
    android:process=":remote" />

android:process 属性中 :的作用就是把这个名字附加到你的包所运行的标准进程名字的后面作为新的进程名称。

这样配置会调用 onCreate() 两次。

Theme && Style

Style 是一组外观、样式的属性集合,适用于 View 和 Window 。

Theme 是一种应用于整个 Activity 或者 Application ,而不是独立的 View。

SQLiteOpenHelper.onCreate() 调用时机?

在调getReadableDatabase或getWritableDatabase时,会判断指定的数据库是否存在,不存在则调SQLiteDatabase.onCreate创建, onCreate只在数据库第一次创建时才执行。

Removecallback 失效?

Removecallback 必须是同一个Handler才能移除。

Toast 如果会短时间内频繁显示怎么优化?

public void update(String msg){
  toast.setText(msg);
  toast.show();
}

Notification 如何优化?

可以通过 相同 ID 来更新 Notification 。

应用怎么判断自己是处于前台还是后台?

主要是通过 getRunningAppProcesses() 方法来实现。

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
    if (appProcess.processName.equals(getPackageName())) {
        if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            Log.d(TAG, String.format("Foreground App:%s", appProcess.processName));
        } else {
            Log.d(TAG, "Background App:" + appProcess.processName);
        }
    }
}

FragmentPagerAdapter 和 FragmentStateAdapter 的区别?

FragmentStatePagerAdapter 是 PagerAdapter 的子类,这个适配器对实现多个 Fragment 界面的滑动是非常有用的,它的工作方式和listview是非常相似的。当Fragment对用户不可见的时候,整个Fragment会被销毁,只会保存Fragment的保存状态。基于这样的特性,FragmentStatePagerAdapter 比 FragmentPagerAdapter 更适合用于很多界面之间的转换,而且消耗更少的内存资源。

Bitmap的本质?

本质是 SkBitmap 详见 Pocket

SurfaceView && View && GLSurfaceView

  • View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢。

  • SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;View的子类,类似使用双缓机制,在新的线程(也可以在UI线程)中更新画面所以刷新界面速度比 View 快,但是会涉及到线程同步问题。

GLSurfaceView:openGL专用。基于SurfaceView视图再次进行拓展的视图类,专用于3D游戏开发的视图。

文末送福利啦!!

我总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料,免费分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
资料领取方式:点击链接加入群聊【Android开发交流】:https://jq.qq.com/?_wv=1027&k=57fcAxd,找群管理免费领取。备注一下简书看到的来领取资料就可以了!

    原文作者:Android架构木木
    原文地址: https://www.jianshu.com/p/8f4499cb1fb4
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞