2019 Android常问面试题总结(简述)

  • mvp mvvm
    ViewModel 承担了 Presenter 中与 view和 Model 交互的职责;
    与 MVP模式不同的是,VM与 V 之间是通过 Datebingding 实现的,而 P是持有 View 的对象,直接调用 View 中的一些接口方法来实现;
    ViewModel可以理解成是View的数据模型和Presenter的合体;
    通过双向绑定(松耦合)解决了MVP中Presenter与View联系比较紧密的问题;

  • 自定义view
    测量:onMeasure()决定View的大小;
    布局:onLayout()决定View在ViewGroup中的位置;
    绘制:onDraw()决定绘制这个View。

  1. 自定义属性;
  2. 选择和设置构造方法;
  3. 重写onMeasure()方法;
  4. 重写onLayout()方法;
  5. 重写onDraw()方法;
  6. 重写其他事件的方法(滑动监听等)。
  • 事件分发机制

    MotionEvent.ACTION_DOWN:按下View(所有事件的开始)
    MotionEvent.ACTION_MOVE:滑动View
    MotionEvent.ACTION_CANCEL:非人为原因结束本次事件
    MotionEvent.ACTION_UP:抬起View(与DOWN对应)

    Activity => ViewGroup => View 的顺序进行事件分发,然后通过调用 onTouchEvent() 方法进行事 件的处理。我们在项目中一般会对 MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_CANCEL 分情况进行操作。

    dispatchTouchEvent
    onInterceptTouchEvent
    onTouchEvent
    onInterceptTouchEvent有两个作用:1.拦截Down事件的分发。2.中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。

    1、ViewGroup的dispatchTouchEvent接收到touch事件,调用onInterceptTouchEvent查看是否拦截。
    2、如果拦截事件,则不传递事件到子View。在ViewGroup本身的onTouchEvent中处理。
    3、如果没有拦截事件,则传递到子View的dispatchTouchEvent.
    4、子View如果是ViewGroup,则回到1.
    5、子View如果是View, 则查看是否有注册OnTouchListener
    6、View如果没有注册onTouchListener或者OnTouchListener返回false,则执行onTouchEvent

  • Looper.prepare()和Looper.loop()
     Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,使用Looper.prepare()和Looper.loop()创建了消息队列就可以让消息处理在该线程中完成。

  • android onTouchEvent和setOnTouchListener中onTouch的区别
    OnTouchEvent()方法是获取的对屏幕的各种操作,比如向左向右滑动,点击返回按钮等等。属于一个宏观的屏幕触摸监控。
    OnTouchListener()方法
    是获取某一个控件某一个View的点击监控。
    两者很容易区分。
    区别如下:
    1、如果setOnTouchListener中的onTouch方法返回值是true(事件被消费)时,则onTouchEvent方法将不会被执行;
    2、只有当setOnTouchListener中的onTouch方法返回值是false(事件未被消费,向下传递)时,onTouchEvent方法才被执行。
    3、以上说的情况适用于View对象(事件会最先被最内层的View对象先响应)而不是ViewGroup对象(事件会最先被最外层的View对象先响应)。
    综合来讲:
    onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。
    假如onTouch方法返回false,会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。
    内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。

  • 内存泄漏
    应用可用的内存减少,增加了堆内存的压力
    降低了应用的性能,比如会触发更频繁的 GC
    严重的时候可能会导致内存溢出错误,即 OOM Error

    使用单例模式
    使用匿名内部类
    使用异步事件处理机制Handler
    使用静态变量
    资源未关闭
    设置监听
    使用AsyncTask
    使用Bitmap

      1、单例造成的内存泄露
      解决方法:单例模式引用的对象的生命周期 = 应用生命周期
      2、非静态内部类 / 匿名类
      解决方法:将 MyAsyncTask 变成静态内部类
      3、集合类
      解决方法:在集合元素使用之后从集合中删除,等所有元素都使用完之后,将集合置空。
      
      4、需要手动关闭的对象没有关闭网络、文件等流忘记关闭手动注册广播时,退出时忘记 unregisterReceiver()
      Service 执行完后忘记 stopSelf()EventBus 等观察者模式的框架忘记手动解除注册
      5、static 关键字修饰的成员变量
      6、ListView 的 Item 泄露
    
  • 代码块
    分析:
    父类静态代码块执行前,父类静态变量就已经执行了。
    父类非静态代码块执行前,父类非静态变量就已经执行了。
    上面结论子类同理。

    代码块执行顺序总结:
    父类的静态成员变量—->父类静态代码块—->子类静态成员变量—->子类静态代码块—>父类非静态变量—->父类非 静态代码块—->父类构造方法—->子类非静态变量—->子类非静态代码块—->子类构造方法。

    另外关于代码块的总结:
    在类第一次调用时,静态代码块只执行这一次。
    静态代码块和静态方法只能调用静态变量,因为它们执行时非静态变量还没初始化;
    非静态代码块和非静态方法可以调用任何(静态+非静态)变量。

  • rebase黄金法则
    绝不要在公共的分支上使用它!
    在你运行 git rebase 之前,一定要问问你自己「有没有别人正在这个分支上工作?」。如果答案是肯定的,那就不能rebase

    rebase的优点和缺点
    rebase最大的好处是你的项目历史会非常整洁
    rebase 导致最后的项目历史呈现出完美的线性——你可以从项目终点到起点浏览而不需要任何的 fork。这让你更容易使用 git log、git bisect 和 gitk 来查看项目历史

    安全性,如果你违反了 rebase 黄金法则,重写项目历史可能会给你的协作工作流带来灾难性的影响
    可跟踪性,rebase 不会有合并提交中附带的信息——你看不到 feature 分支中并入了上游的哪些更改

  • MINA流程
    首先先启动一个本地的服务–启动成功后–通知前端可以开始连接了–前端连接成功后 – 就准备发 送消息–服务器接收到消息–回调给前端
    自定义消息格式:
    消息头(一个int类型:表示消息体的长度、一个short类型:表示事件号)+消息体(为字符串,可以假定认为是json字符串)。接下来的很多代码都是以此消息格式为基础编写。

    粘包:发送端为了提高网络利用率,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包再发送个接收端。

    断包:当消息长度过大,那么就可能会将其分片,然后每片被TCP封装,然后由IP封装,最后被传输到接收端。

    当出现断包或粘包现象,接收端接收到消息后,就会不清楚这是不是一个完整的消息,所以必须提供拆包机制。更多关于Socket断包粘包的信息可自行上网搜索,在这里就不一一细说。

  • 布局优化
    布局的层级越少,加载速度越快。
    减少同一层级控件的数量,加载速度会变快。
    一个控件的属性越少,解析越快。
    尽可能使用约束布局。
    将可复用的组件抽取出来并通过include标签使用。
    使用viewstub标签加载一些不常用的布局。
    使用merge标签减少布局的嵌套。
    尽可能少使用包裹内容这个属性,会增加布局measure时的计算成本,已知宽高为固定值,不用wrap_content
    删除控件中的无用属性。

  • 内存优化
    常用数据结构优化,ArrayMap及SparseArray是android的系统API,是专门为移动设备而定制的。用于在一定情况下取代HashMap而达到节省内存的目的,具体性能见HashMap,ArrayMap,SparseArray源码分析及性能对比[10],对于key为int的HashMap尽量使用SparceArray替代,大概可以省30%的内存,而对于其他类型,ArrayMap对内存的节省实际并不明显,10%左右,但是数据量在1000以上时,查找速度可能会变慢。

    枚举,Android平台上枚举是比较争议的,在较早的Android版本,使用枚举会导致包过大,在个例子里面,使用枚举甚至比直接使用int包的size大了10多倍 在stackoverflow上也有很多的讨论, 大致意思是随着虚拟机的优化,目前枚举变量在Android平台性能问题已经不大,而目前Android官方建议,使用枚举变量还是需要谨慎,因为枚举变量可能比直接用int多使用2倍的内存。

    ListView复用,这个大家都知道,getView里尽量复用conertView,同时因为getView会频繁调用,要避 免频繁地生成对象

    谨慎使用多进程,现在很多App都不是单进程,为了保活,或者提高稳定性都会进行一些进程拆分,而实际上即使是空进程也会占用内存(1M左右),对于使用完的进程,服务都要及时进行回收。

    尽量使用系统资源,系统组件,图片甚至控件的id

    减少view的层级,对于可以 延迟初始化的页面,使用viewstub

    数据相关:序列化数据使用protobuf可以比xml省30%内存,慎用shareprefercnce,因为对于同一个sp,会将整个xml文件载入内存,有时候为了读一个配置,就会将几百k的数据读进内存,数据库字段尽量精简,只读取所需字段。

    dex优化,代码优化,谨慎使用外部库, 有人觉得代码多少于内存没有关系,实际会有那么点关系,现在稍微大一点的项目动辄就是百万行代码以上,多dex也是常态,不仅占用rom空间,实际上运行的时候需要加载dex也是会占用内存的(几M),有时候为了使用一些库里的某个功能函数就引入了整个庞大的库,此时可以考虑抽取必要部分,开启proguard优化代码,使用Facebook redex使用优化dex(好像有不少坑)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值