美文网首页
知识点总结

知识点总结

作者: ambitioner | 来源:发表于2019-04-01 21:23 被阅读0次

    一.Activity面试详解

    1.activity生命周期

    4种状态
    running/paused/stopped/killed
    activity生命周期
    android进程优先级: 前台/可见/服务/后台/空

    2.Android任务栈

    3.activity启动模式

    onNewIntent何时调用:在singleTop和singleTask模式下,某个acitivity已经启动。当再次调用的时候,才会调用

    4.scheme跳转协议

    二. Fragment面试详解

    1.Fragment为什么被称为第五大组件

    为什么会成为第五大组件
    使用频率,有自己声明周期,动态灵活加载到activity,更节省内存
    加载到Activity的两种方式
    FragmentPagerAdpter和FragmentStatePagerAdapter的区别
    前者使用于页面较少的,后者适用于页面较多的情况。

    2.Fragment的声明周期

    3.Fragment之间的通信

    fragment调用activity中方法 getActivity

    4.FragmentManager

    三. Service面试详解

    1.service应用场景,与Thread的区别

    service基础 是什么?区别?

    2.启动的两种方式

    startService
    使用:
    生命周期
    onCreate->onStartCommand->onDestroy
    多次调用startService,会多次调用onStartCommand函数,但不会调用onCreate
    特点:与开始服务的组件没有关系,开启服务的组件销毁,服务仍旧会继续运行。
    bindService
    使用:
    生命周期
    onCreate->onBind->onUnBind->onDestroy
    特点:与绑定服务的组件强绑定,绑定服务的组件如果销毁,该服务也会销毁。

    四. Broadcast Receiver面试详解

    1.广播

    定义
    场景 同一app的多个进程 不同app之间的组件之间的通信
    种类 普通广播,有序广播,本地广播

    2.实现广播 receiver

    3.广播实现机制

    4.LocalBroadcastManager详解

    五. Binder机制

    1.Linux内核基础知识

    进程隔离/虚拟地址空间
    系统调用:内核空间,用户空间

    2.Binder通信机制介绍

    为什么使用binder
    binder通信模型
    通信的两个用户进程:手机
    binder驱动:基站
    serviceManager:通讯录
    binder通信原理

    3.AIDL

    使用步骤

    六.Android多线程

    1.Handler面试详解

    1.1 什么是Handler

    1.2 使用方法

    1.3 机制原理

    1.4 handler引起的内存泄露和解决方法

    原因

    静态内部类持有外部类的应用,导致外部类activity无法被释放

    解决方法

    handler内部持有外部acitvity的弱引用,并把handler改为静态内部类,在activity的ondestroy中加入mHandler.removeCallback()

    2.asynctask面试详解

    2.1.什么是asynctask 封装了线程池和handler的异步框架

    2.2.使用方法

    2.3.内部原理

    2.4.AsyncTask的注意事项

    AsyncTask的对象必须在主线程中创建
    execute方法必须在UI线程中加载
    一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报一场
    不适合做长时间耗时的操作,如果要执行长时间操作,最好使用线程池Excutor
    避免内存泄露,解决内存泄露的方法跟handler一样。

    3.handlerThread面试详解

    3.1.是什么

    产生的背景:为了解决 多次创建和销毁线程是很消耗系统资源的。

    3.2.源码解析

    4.intentService面试详解

    4.1.是什么

    一个封装了HandlerThread和handler的异步框架。每次任务完成会自动关闭service。普通service是运行在主线程的,无法处理耗时操作,intentService提供了这种机制。

    4.2.使用方法

    继承intentService,覆写onhandleIntent方法,在里面处理耗时操作。

    4.3.源码解析

    可以启动多个intentService,会将任务存储在队列中依次执行。
    内部是利用handlerThread实现的。

    七.view

    1.绘制问题面试

    1.1.view树的绘制流程

    1.2.measure

    测量是从viewgroup从上到下依次递归测量的。viewgroup是抽象类,里面没有重写onMeasure,如果要自定义viewgroup类的时候必须重写onMeasure,里面定义如何通过遍历子类最后计算出viewgroup的大小。
    onMeasure中有两个参数,分别是widthMeasureSpec, heightMeasureSpec,每个measurespec包含两个值,一个是specmode,一个是specsize。每个view的measurespec是由父控件的measurespec和当前view的layoutparam共同决定的。
    如果为EXACTLY,说明view的layoutparam是具体的size,或者match_parent,此时specsize就是最后的size。
    如果是AT_MOST,说明view的layoutparam是wrap_content,此时specsize需要子view根据自己的情况获取最后的size。
    也就是说当我们自定义view的时候,如果在布局文件中只需要设置具体size或者match_parent两种属性,那么就不需要重写onMeasure。如果需要设置wrap_content,就需要重写onMeasure,计算这种情况下的 控件的大小。
    参考:https://www.jianshu.com/p/d07f633c37e7

    1.3 layout

    onLayout()都是由ViewGroup的子类实现的,他的作用就是确定容器中每个子控件的位置,由于不同的容器有不容的布局策略,所以每个容器对onLayout()方法的实现都不同,onLayout()方法会遍历容器中所有的子控件,然后计算他们左上右下的坐标值,最后调用child.layout()方法为子控件设置坐标

    首先我们要明确布局的本质是什么,布局就是为 View 设置四个坐标值,这四个坐标值保存在View的成员变量 mLeft、mTop、mRight、mBottom 中,方便 View 在绘制(onDraw)的时候知道应该在那个区域内绘制控件。
    自定义viewgroup必须实现onLayout,对子控件进行摆放。
    参考:https://www.jianshu.com/p/0b444c4c5cf6

    1.4 draw

    1.5 getWidth和getMeasureWidth区别

    getMeasureWidth是在onMeasure执行完成后获得的,而getWidth是在onLayout执行完成后获得的
    getMeasureWidth是onMeasure最后通过setMeasuredDimension设置大小后获取的宽度。getWidth是onLayout后,mRight-mLeft获得的。也就是说在onMeasure后可以通过onLayout改变控件的显示宽度。

    2.view的事件分发机制面试

    2.1.为什么会有事件分发机制

    由于view是树形结构,点击屏幕可能引起多个响应,为了确定哪个view进行响应,引入了事件分发机制。

    2.2.三个重要的方法

    dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent
    三者之间的伪代码如下

        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if(onInterceptTouchEvent(ev)){
            consume = onTouchEvent(ev);
        }else {
            consume = child.dispatchTouchEvent(ev);
        }
        return consume;
    }
    

    viewgroup接收到TouchEvent后会将事件通过dispatchTouchEvent分发。如果onInterceptTouchEvent返回true,则事件交由viewgroup的onTouchEvent来处理;如果返回false,则会交给子View的dispatchTouchEvent来处理。
    默认情况下,viewgroup的onterinceptTouchEvent返回false,及不拦截事件。view没有onterinceptTouchEvent,所以view只要已接收到事件,就会传递给自身的onTouchEvent。

    滑动冲突解决

    八.优化

    1.内存溢出oom

    当前占用的内存加上我们申请的内存资源超过了Davik虚拟机的最大内存限制就会抛出out of memory异常。
    主要原因就是bitmap

    1.1 有关bitmap

    (1)图片的存储优化

    图片占用内存计算:图片宽度 x 图片高度 x 一个像素占用的内存大小

    尺寸压缩

    (1)设置inJustDecodeBound=true,,使图片能够没加载进内存就能够获取图片的狂傲。
    (2)设置imSampleSize,只要大于2,就能够压缩图片占用内存。
    (3)单纯改变ImageView不会对图片占用内存有任何的改变,必须针对bitmap本身的优化才起作用。

    质量压缩

    (1)常见的PNG,JPG,WEBP等格式的图片在设置到UI上之前需要经过解码过程;
    使用tinyPNG网站压缩PNG
    使用Webp
    (2)使用RGB_565替代ARGB_8888可以降低图片占用内存;
    RGB_565一个像素占用两个字节,而ARGB_8888一个像素占用四个字节

    内存重用

    使用inBitmap属性,对内存进行重用。
    4.cache
    使用lru算法。
    内部利用linkedHashMap实现,提供了get,put操作,缓存满了之后提供trimToSize方法,移除较早的缓存对象,添加最新的对象

    listview convertview/lru

    1.2 避免在onDraw方法里面执行对象的创建

    容易造成内存抖动,内存抖动积累到一定程度也会造成oom。因为频繁内存抖动会将内存碎片化,从而当需要分配内存的时候,虽然总体上还有内存分配,但是由于这些内存不是连 续的,导致无法分配,系统就直接返回OOM了

    1.3 使用多进程,需非常谨慎

    2.内存抖动

    短时间内创建大量对象,内存达到阈值后,触发gc。内存抖动积累到一定程度也会造成oom。因为
    频繁内存抖动会将内存碎片化,从而当需要分配内存的时候,虽然总体上还有内存分配,但是由于这些内存不是连续的,导致无法分配,系统就直接返回OOM了

    3.内存泄露:

    3.1 java内存泄露基础知识

    指的是无用对象持续占有内存或无用对象的内存得不到及时释放,造成的内存空间的浪费称为内存泄露。

    1.java内存分配策略

    静态存储区(方法区)

    存储静态变量,全局变量。编译的时候已经分配好了,并且该区域存储的变量在整个程序运行的过程中都存在。

    栈区

    方法中的局部变量,一些基本类型的变量,对象的引用变量。方法结束后自动释放。

    堆区

    动态内存分配。存储new出来的对象和数组,由java的垃圾回收器来管理

    2.java如何管理内存

    3.java中的内存泄露

    3.2 android内存泄露

    1.单例.

    因为静态变量存在与app的整个生命周期。如果静态变量持有了某个activity的context,就会造成activity无法释放。

    2.非静态内部类:

    包括成员内部类,局部内部类和匿名内部类。因为非静态内部类会持有外部类的引用

    3.handler

    4.避免使用static

    5.资源未关闭造成的内存泄漏

    6.AsyncTask造成的内存泄漏

    android内存管理
        内存管理机制概述
        分配机制:为每个进程分配机制
        回收机制:
    android内存管理机制
        分配机制:
        回收机制:根据进程优先级回收进程
    内存管理机制的特点
        更少的占用内存
        在合适的时候,合理的释放系统资源(不是说对象不需要了就立刻回收掉就是最好的内存管理,频繁的释放内存
    

    会造成内存抖动,这样会造成anr,oom,卡顿)
    在系统内存紧张的时候,尽可能的释放掉一些非重要资源

    内存优化方法
        service完成任务后,尽量停止它
        在UI不可见的时候,尽可能的释放掉一些非重要资源
        在系统内存紧张的时候,尽可能多的释放掉一些非重要资源 onTrimMerory
        避免滥用Bitmap导致的内存浪费
        使用针对内存优化过的数据容器,避免使用枚举
        避免使用依赖注入的框架
        使用zip对齐的apk
        使用多进程 例如开启一个进程 定位,webview,推送    
    内存溢出vs内存泄露
        内存溢出oom:
        内存泄漏:
    

    4.UI卡顿

    4.1 UI卡顿原理

    60fps->16ms
    Android系统每隔16ms触发对android进行渲染,如果每次都能渲染成功,就能够达到流畅的画面,也就是每秒60帧画面。

    4.2 UI卡顿原因分析

    1. 人为在UI线程中做轻微耗时操作,导致UI线程卡顿

    2. 布局Layout过于复杂,或者过度绘制,无法在16ms内完成渲染。

    3. 同一时间动画执行的次数过多,导致CPU或GPU负载过重。

    4. View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染。

    5. 内存频繁触发GC过多,导致暂时阻塞渲染操作。gc过程会暂停所有线程的工作。

    4.3 UI卡顿总结

    (1)布局优化

    消除冗余嵌套和过复杂的布局

    Gong替换invisible
    尽量使用weight代替长宽
    如果存在非常复杂的嵌套,可以考虑使用自定义的view。减少measure和layout的次数

    (2) 列表及adpter优化

    在滑动过程中,只加载缺省图片,停止的时候才加载图片和数据

    (3) 背景和图片等内存分配优化

    去掉不必要的背景
    图片要进行压缩

    (4) 避免ANR

    5. 冷启动优化

    5.1什么是冷启动

    (1)冷启动的定义

    第一次启动应用或者被进程杀死后重新启动。
    启动之前,系统中没有该应用的任何进程信息。

    (2)冷启动热启动的区别

    a.启动之前有没有该应用的进程
    b.要不要启动Application的类

    (3)冷启动的时间的计算

    这个时间值从应用启动(创建进程开始计算),到完成视图的第一次绘制(即Activity内容对用户可见)为止。

    5.2 冷启动流程

    Zygote进程汇总fock创建出一个新的进程
    创建和初始化Application类,创建MainActivity类。
    Inflate布局、当onCreate、onStart、onResume方法都走完
    contentView的measure、layout、draw显示在界面上

    Application的构造器方法attachBaseContextonCreate()Activity的构造方法onCreate()配置主题中背景等属性onStartonResume测量布局绘制显示在界面上

    5.3 启动优化

    (1) 减少onCreate方法的工作量

    (2) 不要让Application参与业务操作

    (3) 不要在Application进行耗时操作

    如果耗时操作过多,应用冷启动后会出现白屏现象。
    解决方法:https://www.jianshu.com/p/436b91175826

    (4) 不要以静态变量的方式在application中保存数据

    (5) 布局/mainThread

    6 其他优化

    6.1 android中不要用静态变量存储数据

    App转入后台,由于内存过低,系统可能会将app进程杀死。但是系统为了用户体验,会将最后的Activity恢复,而此时app的进程使重新开启的,静态变量会重新初始化。该Activity如果应用了静态变量,会造成nullpointer的错误

    6.2 有关Sharepreference的问题

    (1)不能跨进程同步

    每个进程都有sharepreference的副本,只有在进程结束的时候才会同步。

    (2)Sharepreference的文件过大的问题

    如果文件过大,在获取Sharepreference值的时候,会阻塞主线程,造成卡顿
    如果文件过大,在解析Sharepreference的时候,会产生大量的临时对象,造成频繁GC,造成内存抖动,也会造成界面卡顿,甚至会发生oom

    (3)内存对象序列化

    序列化

    将对象的状态信息转换为可以存储活传输的形式的过程

    Serializeble

    产生大量临时变量,引起频繁gc,造成内存抖动,页面卡顿,严重的会产生oom

    Parcelable

    android独有的序列化方式。不能适用将数据存储在磁盘的情况。适用的场合使进程间通信。使用内存的时候Parcelable性能更高。

    java的垃圾回收机制

    Java的一个重要有点就是通过垃圾收集器GC自动管理内存回收,程序员不需要通过调用函数释放内存。但是并不是说java就不存在内存泄露。虽然简化了程序员的工作,但同时也加重了jvm的工作,这也是Java程序运行速度较慢的原因之一。因为,gc为了能够正确释放对象,gc必须监控每一个对象的运行状态,包括对象的申请、被引用、引用、赋值等,gc都需要进行监控。
    从几个方面来说:

    1.什么时候回收?

    a.在cpu空闲的时候
    b.在堆内存满了的时候
    c.system.gc()调用的时候尝试回收

    2.怎么判断对象可以被回收

    java和c#都是使用根搜索算法(GC Roots Tracing)判断的。这个算法的基本思路就是通过一系列名为“GC Roots”的对象作为起点,从这些几点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

    九. Activity的窗口机制

    每个activity含有一个phoneWindow对象,phonewindow中含有DecorView。phoneWindow是Activity和DecorView的桥梁。DecorView只有一个LinerLayout的子view。包含通知栏,标题栏,内容栏。setContentView就是将xml的view添加到内容栏位置。

    事件分发:Activity接到事件后,会传到Window对象中,window再将事件传递给DeocrView,Decorview传给它唯一的子View,一个ViewGroup,然后递归传递下去。

    相关文章

      网友评论

          本文标题:知识点总结

          本文链接:https://www.haomeiwen.com/subject/qfgbbqtx.html