初中级Android面试宝典笔记

《Android面试宝典》学习笔记

适用于初中级Android面试

一、面试准备

1、简历制作

  • 个人资料

  • 求职意向

  • 专业技能

    • 详细描述掌握的专业技能Java/Kotlin/Android
    • 辅助开发技能的描述Git/AS/第三方源码/设计模式/架构
    • 工作经历
    • 项目经验描述/职责/技术要点
  • 自我评价

    自学能力强、踏实勤奋、爱钻研,热爱研发工作,责任心强;做事认真,工作积极;求知好学,分析问题解决问题能力突出,敢于接受挑战,有毅力耐力;团队合作,善于沟通和协调。

2、 面试问题

  • 离职原因
  • 加班态度
  • 跳槽看法
  • 薪资意见
  • 印象深刻的技术问题
  • 反问面试
    • 晋升机制,期权股份,业务发展,产品/研发等项目运作模式。
  • 自身价值
    • 技术多样性
    • 创新能力
    • 团队战斗力
  • 技术面试要点
    • 自信
    • 主动引导
    • 简明扼要,突出重点
    • 适度扩展
  • 注重礼节

二、Java基础

1、面向对象的热点问题

  • 面向对象和面向过程

  • AOP、OOP

  • 面向对象的特征

    • 封装

      将对象的属性行为封装成,对外隐藏实现细节

    • 继承

    • 多态

      表现出多种形态,具有多样的实现方式

初中级Android面试宝典笔记_第1张图片

这里的名词都是C++语言中的概念;
虚函数,就是Java中的抽象函数的意思;
纯虚类,就是Java中的抽象类;
实现继承就是继承没有抽象函数的基类;
可视继承就是继承抽象类

  • 抽象和封装的区别

    抽象事将食物的共有、本质性的特征抽取描述;

    封装则是将抽象得到的数据和行为相结合构成一个描述类;

  • 接口和抽象类的区别

    • 语法层面
    抽象类 接口
    可以有非抽象函数和变量 只能有public的抽象函数(Kotlin可以有函数默认实现)
    成员变量可以多样化 只能有public static final的成员变量
    可以有静态代码块和静态方法 不能有静态代码块和静态方法
    类只能继承一个抽象类 类可以实现多个接口
    • 设计层面

      抽象类 接口
      对问题领域分析设计得到的抽象概念,是对类的抽象,整体的。 接口是对行为的抽象,局部的。
      继承 is的关系 实现是has的关系

2、集合框架的热点问题

  • ArrayList和Vector的区别

    ArrayList Vector
    基于Object[]实现,具有数组特性,可以自扩容 基于Object[]也具有数组特性,可自扩容
    有索引查询效率高 有索引查询效率高
    线程不安全 线程安全synchronized修饰
    自扩容默认50% 自扩容100%
    若扩容后还不足,则minCapaxity设为size大小 capacityIncrement的赋值与否来确定扩容的方式
  • HashMap的特点

    • 实现Map接口的Key-Value形式
    • 可以Null值,Key是否可NUll?多少个?
    • 无序、非同步安全的
    • 底层存储了Entry对象
  • HashMap的工作原理

    通过Hash算法计算Key的hash值来存储对象(entry)

    调用put时,调用hashCode计算hash值,得到对应table中的位置,若对应Key的table上存在元素,HashMap通过链表将产生碰撞的元素组织起来。冲突元素超过限制(默认是8),换用红黑树替换链表,从而提高效率。

初中级Android面试宝典笔记_第2张图片

3、I/O流的热点问题

  • I/O流常见子类及特点

    • 结点流FileInputStream&FileOutputStream,作用于外部存储(非内存);需文件存在、可读/写;
    • PipedInputSteam&PipedOutputSteam,用于线程操作,自带缓冲区;
    • Buffered I/O Stream,将原始流数据缓存积累成大数据块再批量操作,注意flush的调用方才生效;
    • Data I/O Stream ,常作用于网络数据传输,用作数据过滤流;
    • InputStreamReader/OutputStreamWriter,会将数据自动转码为Unicode字符。
  • I/O流结构

    • 字节流,对应于Java中就是xxxStream
      • ByteArray
      • File
      • Filter
        • Buffered
        • Data
      • Piped
      • Sequence
      • Object
    • 字符流,对应于Java中就是xxxReader/Writer
      • Buffered
        • LineNumberReader
      • CharArray
      • Input/Output
        • FileReader/Writer
      • Piped
  • NIO的作用

    传统I/O操作时阻塞的;

    NIO是非阻塞的,提高程序性能,CPU利用率;

    IO NIO
    面向流 面向缓冲区
    没有缓存区 有缓冲区
    不能前后移动读取流数据的区段 可读取缓冲区的数据区段
    阻塞 非阻塞
    无选择器 有选择器,可用于监控多通道的数据
  • 磁盘I/O的工作机制

    File创建于磁盘,Java有File对象,并有与之关联的FileDescriptor

4、多线程问题Multithreading

  • 多线程的实现方式

    基于硬件及操作系统支持的前提下,Java实现多线程的方式

    • 继承Thread类
    • 实现Runnable接口,接口形式,便于要执行线程任务的类不能既继承Thread有继承其他类的多继承问题
    • 使用ExecutorService、Callable、Future实现有返回结果的多线程,主要是Executor框架中,得到Future对象可以get任务结果
  • 线程的运行状态

    1. 新建状态,被JVM分配堆内存
    2. 就绪状态,调用start之后,处于等待CPU使用权
    3. 运行状态
    4. 阻塞状态,不分配CPU,直到线程重新就绪
      • 对象池状态,即线程执行了某对象的wait函数,则会被放到该对象的等待池中
      • 对象锁状态,即线程执行去获取某对象的同步锁,而不得的时候,就会被放到该对象的锁池中
      • 其他状态,如线程执行sleep,或者调用其他线程的join,或者进行I/O请求的时候,造成的阻塞
  • 终止线程的方法

    • 使用退出标志,即run函数执行完毕,正常退出
    • Thread.interrupt中断线程
    • Thread.stop强行终止,不建议使用,suspend、resume等都会引起不可预料的结果
  • Sleep和Yield

    sleep yield
    是当前线程休眠 暂停正在执行的线程对象,并去执行其他线程。即,交出cpu执行权
    sleep(0)相当于yield
    sleep让自身不占用执行,其他任意优先级的线程都有机会抢到执行权 yield释放cpu交给同优先级,或者高优先级的线程来使用
    sleep(xxx)之后,线程处于阻塞状态 yield之后,线程处于就绪状态
    sleep会抛出InterruptedException yield无异常抛出
    sleep更易于移植
  • Sleep和wait

    • sleep属于Thread的方法,sleep指定时间后,会自动从监控状态恢复,不会释放对象锁;
    • wait是Object的方法,调用wait会使本线程放弃对象锁,进入等待此对象的等待锁定池,且只有该对象notify/notifyAll后,本线程才会进入对象锁定池,准备获得对象锁来进入运行状态;
  • synchronized和lock的异同

    • 均可用于线程安全问题
    • Lock可实现所有synchronized的功能
    • synchronized持有锁资源,可以自动释放锁
    • Lock需要手动释放,载finally中。
    • Lock可以用tryLock方式非阻塞的获取锁
    • 性能消耗的差异
      • 竞争不激烈时,synchronized使用轻量锁或偏向锁,均可有效减少轮询或阻塞的发生;
      • Lock将未获得锁的线程放入等待队列,阻塞,带来切换的消耗;
      • 高竞争时,synchronized使用重量级锁,此时相对处理速度慢,效率低于lock。
      • 数据结构设计或框架设计上,多用lock

5、Java数据结构热门问题

  • Java内存模型

    • 堆栈的理解

    基本类型的变量和对象的引用变量,存放在栈内存;

    堆内存存放对象实例和数组,JVM垃圾回收机制GC

    • Java堆栈代码示例
    public class Stack{
      int[] data;
      int maxSize;
      int top;
      
      public Stack(int maxSize){
        this.maxSize = maxSize;
        data = new int[maxSize];
        top = -1;
      }
      
      //push
      public boolean push(int data){
        if(top+1==maxSize){
          System.out.println("栈已满!");
          return false;
        }
        this.data[++top] = data;
        return true;
      }
      
      //pop
      public int pop() throws Exception{
        if(top==-1){
          throw new Exception("栈已空!");
        }
        return this.data[top--];
      }
      
      //test
      public static void main(String[] args) throw Exception{
        Stack stack = new Stack(1000);
        stack.push(1);
        stack.push(3);
        while(stack.top>=0){
          System.out.println("stack pop 后 "+stack.pop());
        }
      }
    }
    
  • 简述对的理解

    • 非线性结构,有节点和分支,具有层次关系的数据描述
  • 如何遍历二叉树

    • 先序、中序、后序三种,均可递归和非递归

6、设计模式的热点问题

  • 单例模式的理解

    • 只有一个实例对象
    • 必须是自己创建自己的唯一实例
    • 必须给其他类提供该唯一实例对象的获取方式

    为了避免状态不一致,常见的有日志对象、线程池、缓存、对话框、打印对象、驱动对象等

    常见的5种单例模式写法

    //饿汉式,非线程安全
    class Singleton{
      private static Singleton instance = new Singleton();//内部创建对象实例
      private Singleton(){}//私有构造函数
      //对外提供获取单例对象的函数
      public static Singleton getInstance(){
        return instance;
      }
    }
    
    //懒汉式,线程安全的
    class Singleton{
      private static Singleton instance = null;
      private Singleton(){}
      
      public static synchronized getInstance(){
        if(instance==null){
          instance = new Singleton();
        }
        return instance;
      }
    }
    
    //枚举方式,Jvm创建模式也是静态的,所以线程安全的
    enum Singleton{
      INSTANCE
    }
    
    //静态内部类 线程安全的
    class Singleton{
      //静态内部类持有外部对象
      private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
      }
      
      private Singleton(){}
      //注意这里函数get是final的
      public static final Singleton getInstance(){
        return SingletonHolder.INSTANCE;
      }
    }
    
    //静态代码块,线程安全
    class Singleton{
      static{
        Singleton instance = new Singleton();
      }
    }
    
  • 工厂模式的理解

    屏蔽创建对象的过程,提高灵活性,作为创建对象的过渡接口;

    • 简单工厂模式,不利于系列创建
    • 工厂方法模式,多形性工厂
    • 抽象工厂模式,产生产品组,不利于新产品

三、Android菜鸟

1、系统架构相关问题

  • Android系统架构

    • 四层架构,应用层、框架层、核心类库和Linux内核

2、Android版本变更特性

  • 5.0特性
    1. materialDesign
    2. 多设备支持
    3. 全新通知中心
    4. 64位ART虚拟机
    5. 电池续航改进JobScheduleAPI
    6. Recent 最近使用
    7. 系统数据加密
    8. 独立数据保存、搜索改进、新Api支持、蓝牙4.1、USB Audio及多人分享等
  • 6.0特性
    1. 运行时权限管理
    2. 网页体验提升
    3. App LInks应用关联
    4. Android Pay
    5. Fingerpirnt Support指纹支持
    6. Power&Change 电量管理
  • 7.0特性
  • 8.0特性
  • 9.0特性
  • 10.0特性
  • 11.0特性
  • 12特性

3、四大组件

  • Activity的生命周期

    • 五种状态,启动、运行(可见、有交点、可交互)、暂停(无交互)、停止(完全不可见)、销毁
    • 启动和销毁状态属于过渡态,不会停留此状态下
    • 回调函数onCreate–>onStart->onResume->onPause->onStop->onDestroy,另有onRestart
  • 横竖屏切换

    • 不配置android:configChanges时候
      • 切横屏:onSaveInstanceState->onPause->onStop->onDestroy->onCreate->onStart->onRestoreInstanceState->onResume
      • 切竖屏:onSaveInstanceState->onPause->onStop->onDestroy->onCreate->onStart->onRestoreInstanceState->onResume
    • 设置android:configChanges="orientation"时候,切横竖屏都只会走一次生命周期
    • 设置android:configChanges="orientation|keyboardHidden"时,切横竖屏不会走生命周期回调,只会执行onConfigurationChanged函数
  • Activity的启动方式

    • 显式intent调用,需要有class的直接引用或者className
    • 隐式启动,通过带有action的intent调用
    • 理解manifest中标签的含义
  • Activity启动模式

    • standard标准模式,例如闹钟应用
    • singleTop栈顶复用模式,例如浏览器tab
    • singleTask栈内唯一模式,例如浏览器主界面
    • singleInstance独立栈模式,例如来电界面
  • Activity之间传递数据

    • Intent传参,基础数据类型、数组、bundle、serializable、parcelable

    • Intent最大参数1024KB数据,也就是Binder的数据大小

  • Intent和PendingIntent区别

    intent pendingIntent
    即时性 延时
    程序结束则Intent终止 仍然有效
    需要context调用 自带context
    运行在原task中 新task
    一般用于四大组建Activity、service、broadcaseReceiver之间传参 一般用于消息通知
  • 如何安全退出多个Activity

    • 抛异常
    • 记录已经打开的Activity并逐个关闭
    • 特定广播关闭其他activity
    • startActivityForResult递归关闭
  • 应对Activity被系统回收

    内存不足、切换配置、节省电量等时候可能会被回收。注意onSaveInstanceState保存状态

  • Service启动方式

    • 运行于主线程(如果在子线程中调用呢?)
    • startService,启动后执行到自身结束,不受调用者关联影响。
    • bindService,通过跨进城IPC机制通讯,调用者和service关联,并能够交互通信。调用unbind销毁service

    综合而言,bindService启动服务并能调用服务内部的方法。

  • 常用的混合调用方式

    start->bind->unbind->stop

  • service生命周期

    • startServce:onCreate->onStartCommand->onDestory,被调用stopService或者自身stopSelf
    • bindService: onCreate->onBind->onUnBind->onDestroy,被调用unBindService
  • 广播相关

    • 无序广播,sendBroadcast
    • 有序广播,sendOrderedBroadcast,可用abortBroadcast拦截广播
    • 另还有必达的广播、粘性广播、本地广播等,后序补充??

    android:property属性配置优先级

    • 静态注册、动态注册regiseterReceiver,注:高版本以后,广播策略有变化限制
  • EventBus事件总线

    • 三部分Event、Subscriber、Publisher

    • 初中级Android面试宝典笔记_第3张图片

    • 优点,代码简洁优雅、使用方便、开销小、有助于代码接耦

  • ContentProvider的理解

    用于不同应用程序间的数据共享,如通讯录、系统相册等。

    不论数据源的形式如何,ContentProvider都按照表的形式对外提供,CURD也就是增删改查操作,query、insert、update、delete

    • getContentResolver来获得ContentResolver操作ContentProvider提供的数据
    • ContentProvider提供数据共享,并规定URI给外部
    • ContentResolver使用URI来CRUD操作数据
    • ContentObserver用于监听ContentProvider的数据变化

4、Fragment相关问题

在3.0开始出现,必须依赖于Activity,可以动态加载和静态加载;

动态加载用到事务,事务具有原子性、不可拆分的操作。

开启事务->添加fragment->提交事务

  • Fragment向下兼容使用support包

  • 生命周期onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach

  • Fragment和Activity的交互

    • Activity可以有Fragment的对象引用,或者fragmentManager中findFragmentByTag/ById
    • Fragment中可以有getActivity获取Activity的引用
    • 切换fragment,使用fragmentManager中的FragmentTranscation调用replace而后commit
    FragmentManager fm = getFragmentManager();
    FragmentTranscation ft = fm.beginTranscation();
    //示例fragment
    XXXFragment fg = new XXXFragment();
    ft.replace(R.id.content,fg);
    ft.commit();
    

5、控件相关问题

  • RecyclerView

    在5.0出现的控件,用以替换listView、GridView等,有Adapter、ViewHolder、LayoutManager、ItemDecoration、ItemAnimator等几部分分工协作

  • WebView控件

    • loadUrl加载网页资源,也可以是本地的Html资源
    • loadDataWithBaseURL,加载字符资源
    • getSettings里面配置必要的webView设置
    • 若处理返回事件,需要override对应backPress函数和keyDown事件,并在WebView的shouldOverrideUrlLoading中处理
    • WebView桥接Java和JS交互,使用@JavascriptInterface注解
      • Java调用Js,使用loadUrl可以调用Javascript语句
      • JS调用Java,需要Java中有@JavascriptInterface的注解的函数,然后webView.addJavascriptInterface 添加进来,并提供js调用的别名;而后js中就可以调用

6、数据处理的相关问题

  • XML解析

    • Dom解析

      基于文档驱动的解析,构建Dom树,在内存中持久,可修改数据和结构

      优点:直观、简单,适用于小文件

      缺点:加载整个XML文件,资源消耗大,不适合大文件

    • SAX解析

      Simple API for XML,基于事件的解析器,扫描文件的标签;

      优点:效率高、内存占用小

      缺点:需要代码负责tag的处理逻辑,适用麻烦,单向导航,不便于反问文档的不同部分,不支持XPath

    • Pull解析

      类似于SAX,基于事件,但是在开始时就完成了大多数处理,而非坚挺tag结束;

      优点:小巧轻便、解析速度快、简单易用

  • Json数据

    • 有数字、字符串、boolean、array、object、null等组成;
    • Json只有对象{}和数组[]两种结构
    • 解析Json可用JsonObject/JsonArray,或者开源库Gson
    • JsonReader使用流的形式读取json数据,类似于PUll解析,beginObject/beginArray,close;
  • SQLite相关

    数据库的表对应关系,一对一、一对多、多对多;常见的数据库框架greenDao、Realm、Room;

    • SQLiteDatabase操作数据库

      • openOrCreateDatabase
      • insert
      • delete
      • query
      • update
      • execSQL
      • close
    • SQLiteOpenHelper

      • getWriteableDatabase
      • getReadableDatabse

      调用如上函数时候,数据库若无,则会被create创建

    • Cursor

      • getCount、isFirst、isLast、moveToFirst/last/next/previous、getColumnindexOrthrow、getInt/getString

6、数据加密相关

  • base64编码

  • AES加密,强安全性、高性能、高效率、易用灵活

    • 轮变化、圈数、密钥扩展
    • 迭代的、对称密钥分组的密码
    • 加密数据块长度128bit,密钥长度可以是128bit,192bit、256bit
    • 数据块及密钥长度不足时自动补足
  • DES加密,密钥长度小于56位,所以被AES代替了

  • RSA加密

    公钥加密算法、非对称加密;

    两个大素数的乘积,作为公钥;自身作为私钥;

    效率略低,安全性高;

  • MD5算法

    数字摘要 Message-Digest Algorithm 5,用于确保数据信息的完整、一致性

    • 压缩性,MD5计算结果长度固定
    • 易计算
    • 抗修改,原始数据的改动会引起md5的变动
    • 强碰撞性,较难有不同数据源的同一md5值

    常用于密码摘要;

7、网络交互的相关问题

  • Http协议特点

    • 简单快速
    • 灵活
    • 无状态
    • 常见header和状态吗code
      • Host、Charset、Connection、Form、timeOut
      • 200、302 重定向、404、找不到url资源、500 服务器错误
    • Http的请求和响应
    //简单的示例
    URL realUrl = new URL(requestUrl);
    HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
    conn.setDoOutput(true);
    conn.setUseCaches(false);
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Connection","Keep-Alive");
    ...
      
    //响应
    if(conn.getResponseCode()!=200){
      throw new RuntimeException("请求url失败");
    }
    InputStream is = conn.getInputStream();
    String result = readData(is,"GBK");
    conn.disconnect();
    
  • POST请求的几种形式

    • Form表单形式
    • JSON数据形式
    • 文件形式
    //1、form
    post.setEntity(postEntity);
    //2、json
    post.addHeader("Connect-Type","applicatin/json");
    post.setEntity(new StringEntity(jsonStr));
    //3、file
    MultipartEntity entity = new MultipartEntity();
    ContentBody cb = new FileBody(file);
    entity.addPart("img",cb);
    post.setEntity(entity);
    //服务端可以根据content-type判断数据请求类型
    
  • Socket通信

    socket是对tcp/ip的封装api,StreamSocket和DatagramSocket(使用udp)

    • 基于TCP的socket

      ServerSocket serverSocket = new ServerSocket();
      Socket socket = serverSocket.accept();//阻塞的
      
      //客户端
      SocketClient client = new SocketClient();
      client.getOutputStream();
      
    • 基于UDP的数据传输

      byte data[] = new byte[1024];
      DatagramSocket packet  = new DatagramSocket(data,data.length);
      packet.receive();//也是阻塞的
      
      packet.send();
      

    Http和socket的区别在于,http是请求–响应式的,socket可以双向通讯;

  • Volley框架

    适用于数据量小、通信频繁的网络操作;

    • StringRequest、JsonObjectRequest、JsonArrayRequest、ImageRequest
    //RequestQueue是请求队列,根据内部算法,可适时的并发的发出队列的请求,一个requestQueue即可
    RequestQueue mQueue = Volley.newRequestQueue(context);
    StringRequest request = new StringRequest();//这里可以设置post,get的方式
    mQueue.add(request);
    
  • Volley异步加载图片

    ImageLoader内部使用IamgeRequest,做了缓存以及过滤重复请求等。

    1. 创建RequestQueue、ImageCache、ImageLoader对象;
    2. 通过ImageLoader获取ImageListener
    3. 调用ImageLoader的get
  • Volley的NetworkImageView加载网络图片

    netImageView.setImageUrl("");

四、Android大神

1、线程相关问题

  • 线程间通信

    Android是UI单线程机制,主线程避免ANR,所以存在需要子线程交互的问题。线程间通信可用Hanlder

  • 线程池的理解

    面向对象的编程中,创建/销毁 对象都是相对耗时消耗资源的。

    尽可能减少对象的创建和销毁的频次,用到线程池。

    概念,优点,使用方式;

    多线程应用在启动之初,创建一个线程集合,存放一定量的线程空闲队列中;不消耗cpu,占用较少内存;

    有请求的时候,分配任务给空闲线程;

    预制线程不足用时,线程池可自由创建新的线程,来处理请求任务;

    超出最大设定线程数的时候,抛出异常,拒绝任务;

    任务清闲时候,会移除停用状态的线程;

    • 线程池可提高性能、减少CPU的消耗,控制并发线程数,避免内存过度消耗;
  • 如何创建线程池

    ThreadPoolExecutor,提供管理任务执行、线程调度、线程池管理的功能;

    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler){
      
    }
    
    • corePoolSize 核心线程数
    • maximumPoolSize 线程池维护线程最大数
    • keepAliveTime 维护线程所允许的空闲时间
    • unit 空闲时间的单位
    • workQueue 缓冲队列
    • threadFactory 新建线程用的工厂类
    • handler 线程池拒绝任务时候的处理策略

2、多媒体相关

  • Android中动画

    • 补间动画 Tween Animation
      • 旋转、平移、缩放、透明度
      • 不改变控件位置属性
    • 帧动画 Frame Animation
      • 加载一系列的图片资源,逐帧播放
    • 属性动画 Property Animation
      • 类似补间动画,但是修改控件属性
  • Interpolator动画差值器

    加速、减速、重复、弹跳等不同的动画细节效果;

    1. 在res/anim下创建interpolator的差值器

      <cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
                         android:cycles="3"/>
      
    2. 在res/anim下创建动画xml

      <translate xmlns:android="http://schemas.android.com/apk/res/android"
                 android:fromXDelta="0"
                 android:interpolator="@anim/cycle_3"
                 android:toXDelta-"10"
                 android:duration="500"/>
      
    3. 在代码中控件使用动画资源

      Animation shake = AnimationUtils.loadAnimation(this,R.anim.shake);
      et_phone.startAnimation(shake);
      
  • Android中常见的视频播放方式

    • 自带播放器App

      Uri uri = Uri.parse("xxxx/xxx.mp4");
      Intent intent = new Intent(Intent.ACTION_VIEW);
      intent.setDataAndType(uri,"video/mp4");
      startActivity(intent);
      
    • VideoView控件

      videoView.setMediaController(new MediaController(context));
      videoView.setVideoURI(uri);
      videoView.start();
      videoView.requestFocus();
      
    • MediaPlayer&SurfaceView

      SurfaceView属于绘图容器,可以直接从内存或者DMA等硬件接口取得图像,可以在主线程之外的线程向屏幕绘图。可与MediaPlayer结合使用。

      1. MediaPlayer加载视频文件
      2. 创建布局文件SurfaceView,设置SurfaceHolder的Callback;
      3. 调用mediaPlayer的setDisplay,输出图像到surfaceView
      4. mediaPlayer的start、stop、pause操作控制;
  • Vitamio视频框架/ExoPlayer框架

3、机制相关问题

  • Handler运行机制

    事件驱动型程序设计模型,与其他线程协同工作,接收其他线程消息并更新主线程;

    App点击事件的响应、Activity的启动、更新界面等,都是handler的应用;

    handler可用于异步请求、定时操作;

    • Message

      线程间的消息

    • MessageQueue

      消息集合,用以存放Runnable和Message

    • Looper

      不断循环消息队列,取出消息

    • Handler

      接收消息回调

    如需在自己线程创建handler,则必须调用Looper的perpare()和loop();

    初中级Android面试宝典笔记_第4张图片

    1. 在UI线程创建handler
    2. 在子线程中调用handler的sendMessage,消息会被存放到UI线程的MessageQueue中去。因为handler是UI线程创建的;
    3. Looper会取出MessageQueue中的消息,分发给hanlder
    4. handler中的handlerMessage回调,处理消息;
  • 事件驱动型程序设计模型

    特点:

    1. 有消息队列,用以存放消息
    2. 有轮询器,用以处理消息队列,无消息时候就休眠
    3. 有消息实体,每个消息都与一个消息处理器handler绑定。handler生命周期很短。

    避免传统时间模型的持久轮询,阻塞耗费cpu资源;

  • AsynaTask异步任务的理解

    为耗时操作开启新线程,AsyncTask是抽象类;Params、Progress、Result三个范型参数;

    • Params,启动任务的入参,如Url,执行数据等;
    • Progress,后台执行任务的百分比;
    • Result,执行任务的返回结果;

    可用Void表示空参数类型;

    • onPreExecute 准备执行,预初始化的必要操作
    • doInBackground 核心的后台任务逻辑,返回参数传递到onPostExecute中。可食用publishProgress发布进度值,到onProgressUpdate中,可用于UI显示进度
    • onProgressUpdate 进度的更新
    • onPostExecute 完成任务后后台结果处理。

    AsyncTask适用于小型、简单的异步处理。

注:AsyncTask后续版本已经废弃,看似比Handler简单轻量,实则更耗资源;

类名 优点 缺点
AsyncTask 简单、快捷、过程可控 多个异步操作并都去更新UI时,变得复杂
Handler 结构清晰、功能定义明确 单个后台异步处理时,显得代码繁多,结构相对复杂
  • Android的事件分发

    Android的手势冲突,多用内部拦截或外部拦截处理;View的分发机制涉及dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个重要函数;

    • dispatchTouchEvent,只要事件传递到当前View,就会调用。内部判断是否interceptTouchEvent,来确定时自身消费,还是分发给子View

    初中级Android面试宝典笔记_第5张图片

    • 图示中、super/true/false代表的是return返回值,super调用父类实现;

    • onInterceptTouchEvent在dispatchTouchEvent中调用,用以判断自身消费还是向下分发;

    • ouTouchEvent也是在dispatchTouchEvent中调用用于处理事件,返回值false则表示自身不消费也不拦截,true表示自身消费掉;

  • Android消息推送

    消息推送的实现有pull方式、push方式;

    • pull表示client定期请求,频次低则消息不及时,频次高,则耗费网络与内存cpu等资源

    • push则是通过长链接实现服务器到client的消息推送;消耗电量、占用资源。

  • 如何绘制View

    简单说分为三步:measure、layout、draw

    • onMeasure,测量View的宽高数据
    • onLayout,ViewGroup中用于确定子view的位置关系
    • onDraw绘制view自身的背景、边框、子view等
  • OAuth2的认证机制

    Open Authorization,获取第三方服务授权的方式;

    安全、开放、简易;

    服务令牌,而不需要密码账号,来获取用户信息数据

    1. 用户访问3rd server,需要userInfo
    2. 3rd server请求用户User Server
    3. User Server验证3rd Server后,给它一个临时Token
    4. 3rd server拥有token后,向User Server请求授权
    5. 用户在User Server上确认授权,以及配置授权信息Info
  • AIDL的理解

    Android进程间通信机制,进程间不能共享内存;Inter Progress Communication;

    AIDL Android Interface Definition Language,类似Java 接口语法;

    1. 接口名与AIDL文件名必须相同
    2. client、server中AIDL的皆苦文件包名必须相同
    3. 接口和方法前,不能加权限修饰符和final、static等
    4. 默认支持基本数据类型int、long、boolean、String等及List、Map、Charsequence
    5. 对List、Map的元素必须是aidl支持的类型
    6. 自定义类型作为参数或返回值,则必须实现Parcelable接口
    7. 所有非Java基本数据类型的参数,必须加上in、out、inout标记,用以标记入参还是返参;Java原始类型默认的标记为in,不能是其他;
    8. 自定义类型和aidl即使在同一包下,生成的其他接口类在aidl中也需要import导入;
    9. 需要一个service类协同使用
  • 说明AIDL的使用

    A应用调用B应用的服务,得到计算结果;

    1. 在B中创建aidl文件
    2. B中实现aidl的接口,binder
    3. B中创建service,用以返回binder
    4. 把B中的aidl复制到A中
    5. A调用B中定义的service即可,隐式调用;

4、优化相关问题

  • 如何优化Listview

    1. 复用convertView
    2. 定义存储控件引用类的viewHolder
    3. 数据粉分页加载、分批加载
    4. 图片处理
      • WeakRefrence弱引用
      • 图片压缩
      • 及时释放资源

    避免BaseAdapter中使用static全局变量,尤其避免其引用context,引起内存泄漏

    避免ListView的Adapter中使用线程,其生命周期不可控,避免内存泄漏;

  • Android布局优化

    1. 复用布局片段
    2. 标签减少层级填充
      1. 根结点是FrameLayout可并入到Activity自身根结点,此时background、padding无效
      2. 结合include使用
    3. ViewStub延迟加载
    4. 合理的布局方式Releative、LinearLayout、ConstraintLayout等

    嵌套层级深引起堆栈溢出问题,推荐层级小于10,view个数小于80;

  • 使用Hierarchy Viewer分析布局

  • Android中使用的引用

    • 强引用,即使OOM也不回收
    • 软引用,用以实现内存敏感的高速缓存,内存空间不足时候,GC可能回收
    • 弱引用,更短的生命周期,一经发现,不论内存足否,都会标记回收。
    • 虚引用,形同虚设,用以跟踪垃圾回收器的活动。不会决定对象的生命周期,必须与引用队列联合使用。
  • 如何处理网络图片产生的OOM

    图片占用内存大小 = 总像素数 x 单位像素

    颜色模式 单位像素空间
    ALPHA_8 1 byte
    ARGB_4444 2 bytes
    RGB_565 2 bytes
    ARGB_8888 4 bytes
    1. 调整图片大小,根据显示需要来缩放,缩放计算的时候,Options.inJustDecodeBounds仅计算宽高,而不完全加载,节省内存;
    2. 适当的颜色模式
    3. 及时回收图片资源
    4. LruCache缓存图片,复用
  • 如何检测内存泄漏

    • DDMS-Heap
    • MAT,Memory Analyzer Tool
    • 解决内存泄漏的点
      • 使用单例时候注意context的引用,避免Activity持有过长
      • 避免非静态内部类中创建静态实例,会引用外部类
      • I/O的及时关闭
      • 及时回收ThreadLocal的绑定对象
      • 及时回收与有效利用已有对象

5、JNI相关

  • JNI的简单描述

    创建Java工程,声明native方法

    创建.h文件

    编写c/c++代码,函数命名与上述的native方法相关联

    创建.mk文件,配置JNI编译环境

    执行ndk的build

    Java中即可调用

6、异常相关问题

  • 捕获全局异常

    • 创建crashHandler,实现UncaughtExceptionHandler
    • 在Application 中注册为全局默认异常捕获器
    • 在uncaughtException中处理对应异常问题
  • 如何避免ANR

    Application Not responding,程序无响应,Android中有三类常见

    1. KeyDispatchTimeout ,按键/触摸事件无响应,5s超时
    2. BroadcastTimeout 广播无法处理 10s超时
    3. ServiceTimeout 服务无法处理 20s 超时

    注意避免方式

    • 主线程避免耗时操作,如网络、IO、大量计算等
    • 避免广播中的复杂操作,如遇到,可用另起service处理
    • 避免synchronized,死锁等错误处理不当的情况

    增强灵敏性

  • 如何测试

    • Junit单元测试
    • Monkey测试

7、第三方框架相关

  • 支付宝/微信 支付流程

    1. 商户签约
    2. 密钥配置
    3. 集成sdk
  • REST REpresentational State Transfer 表属性状态转移,软件架构风格。通过资源的表现形式来操作资源。

    优点:

    • 可以利用cache提高响应速度
    • 通信无状态,可让不同服务器处理一系列请求中的不同请求,提高服务器的扩展性
    • 浏览器即为client,简化软件需求
    • 相比于其他Http协议之上的机制,REST的软件依赖性更小
    • 不需要额外的资源发现机制

    缺点:

    1. 复杂应用对应URL变长
    2. REST不支持事务
    3. REST安全性不足
    4. 风格规范,并非标准,现实实现各有差异;
  • RESTful Web Service

  • RxJava的理解

    响应式编程框架、专注于异步和控制可观察数据/事件;

    • Observable
    • Subscriber

    通过订阅建立关系,配合schedules调度线程分配,结果中onNext、onCompleted、onError处理不同状态返回。

  • REtrofit库的理解

    使用注解简化网络请求,默认OKHttp为httpClient,使用retrofit的前提是服务器代码遵循REST规范;

    1. 性能最好、处理最快
    2. 配合REST API非常方便
    3. 传输层默认OkHttp框架
    4. 支持NIO,同时支持URL参数替换和查询参数
    5. 返回结果可转换为Java对象(Json字符串或Protocol BuffersProtocol)
    6. 支持Multipart请求和文件上传

8、屏幕适配问题

  • 屏幕适配方案

    • 套图适配,完美适配不失真,较难实现,App臃肿
    • 9patch适配,省精力省时间省内存,减少代码量;不能完全适配;
    • 布局适配
      • 权重适配,约束比例,少用具体值,但复杂页面上效果不好;
      • 约束布局、线性、相对布局;
      • 纯色背景,多用shape代替png
  • 屏幕尺寸、分辨率、像素密度

    • 屏幕尺寸是屏幕物理对角线长度,单位英寸
    • 分辨率只单位像素点数,px,1px为1像素点。如1920x1080
    • 像素密度,单位dpi, dot per inch;即每英寸像素点数

    px 像素单位

    dp/dip density independent pixel,密度无关像素;Android中160dpi 为基准 1dip = 1px ;320dpi时候,则 1dp = 2px

    dpi , dots per inch 每英寸的像素数 ,表示对角线的像素值。例如 1920x1080分辨率 5英寸的屏幕,dpi = 192 0 2 + 108 0 2 / 5.0 \sqrt{1920^2+1080^2}/5.0 19202+10802 /5.0

9、程序打包问题

  • 数字签名的几种模式

    • debug模式
    • release模式

    配置keystore,在AS中build的apk通过AS安装的实质是adb install -t xxx.apk,没有签名也能使用。实际发布,不论是debug还是release的apk,都有签名文件,在apk的解压后签名目录META-INF内有cert文件;

  • 使用相同数字证书的好处

    • 利于维护升级
    • 便于程序模块化设计和开发
    • 可用于多应用共享数据
  • 多渠道打包

    • 普通的gradle的productFlavors配置占位符
    • walle 开源打包框架
  • 代码混淆

    • pro gua r d.cfg配置
    • minifyEnable true
  • 加固

  • 瘦身apk

    • 混淆
    • code clean
    • png压缩 tinyPng
    • svg代替
    • 删除替换support包,冗余jar依赖
    • 动态加载,插件化

你可能感兴趣的:(Android笔记,android,面试)