面试相关

1.Json解析与XML解析

Gson解析和FastJson ,FastJson解析效率高

XML解析,SAX解析、DOM解析、Pull解析

2.Android中几种数据存储方式

(1)使用SharedPreferences存储数据
(2)文件存储数据
(3)SQLite数据库存储数据
(4)使用ContentProvider存储数据
(5)网络存储数据

3.Handler消息机制

Handler消息机制主要包括handler、MessageQueue、Looper

MessageQueue:消息队列,内部存储一组消息,以队列的形式向外提供插入和删除的工作,是采用单链表的数据结构来存储消息

Looper:消息循环,用来处理消息,Looper会以无限循环的形式去查找是否有消息,有就处理,没有就等待

Handler创建时会采用当前线程的Looper来构建内部消息循环系统,如果当前线程没有Looper,就会报错。

4.String、StringBuffer、StringBuilder的区别?

String 类是不可变类,即一旦一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁

StringBuffer、StringBuilder对象代表一个字符序列可变的字符串
两个类的构造器和方法也基本相同,不同的是StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuilder的效率要高于StringBuffer

5.Android系统架构

(1)Linux内核层
Android的核心系统服务依赖于Linux2.6内核

(2)系统运行库层
Android包含一些C/C++库

(3)应用测序框架层
开发人员可以访问应用程序所使用的API框架

(4)应用程序层
开发人员开发的应用

6.Activity的生命周期

onCreate()->onStart()->onResume()->onPause()->onStop()->onDestroy()
最后还有一个onRestart()

7.Fragment的生命周期

onAttach()->onCreate()->onCreateView()->onActivityCreate()->onStart()->onResume()->onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()

8.Service生命周期

(1)当启动服务的时候,首先调用onCreate()方法,然后调用onStartCommand()方法,当第二次在启动服务的时候,只会调用onStartCommand()方法

(2)当关闭服务的时候,调用方法onDestory()

(3)当调用绑定服务的时候,调方法onCreate()->onBind()

(4)调用unbindService()后,调用方法:onUnbind()->onDestory()

9.Android中的动画

(1)帧动画
原理是将一张张单独的图片连贯的进行播放,从而产生一种动画的效果

(2)View动画:位移动画、透明度动画、旋转动画、缩放动画

(3)属性动画
API11之后才可以使用

10.Android中的四大组件

Activity、BroadCastReceiver、ContentProvider、Service

11.Android中的常用布局

线性布局、相对布局、帧布局、表格布局、绝对布局

百分比相对布局、百分不帧布局

12.Android的数据存储

(1) 使用SharedPreference存储

(2)文件存储

(3)SOLite数据库存储

(4)使用ContentProvider存储数据

(5)网络存储数据

13Activity的启动模式

(1)standard:标准模式,也是系统默认的启动模式,每次启动一个Activity都会重新创建新的实例,不论这个实例在任务栈中是否存在

(2)singleTop:栈顶复用模式

假如,Activity A启动了Activity B ,就会判断A所在的任务栈栈顶是否是B的实例。如果是,则不创建新的 activity B 实例而是直接引用这个栈顶实例,同时 onNewIntent 方法会被回调,通过该方法的参数可以取得当前请求的信息;如果不是,则创建新的 activity B 实例。

(3)singleTask:栈内复用模式

如果不存在,就会重新创建一个任务栈
如果存在,就调到栈顶

(4)singleInstance:单实例模式
Activity只能单独存在一个任务栈中

14.Android中的广播

自定义一个类继承BroadCastReceiver,实现onReceive方法

有两种注册方式:在清单文件中注册(静态注册)、在代码中注册(动态注册)

两种注册方式的区别:

静态注册是常驻型广播,动态注册是非常驻型广播
在静态注册广播中启动Activity会报错,在动态注册广播中不会报错,当App退出后,仍可以接受广播
动态注册,当App退出后,也就没有办法接受广播了

15.Android中的ANR

ANR的全称application not responding 应用程序未响应

Android规定,Activity如果5秒之内无法响应屏幕触摸事件或者键盘输入事件就会出现ANR,而BroadcastReceiver如果10秒之内还未执行完操作也会出现ANR

不要在UI线程中做过多的耗时操作,不要在子线程中更新UI,避免在广播里做耗时操作或者计算

/data/anr/traces.txt 文件,定位ANR发生的原因

16.Service的两种启动方法,有什么区别

binderService时,Service与Context相关联,并且Service的生命周期依赖于Context

startService方法启动一个Service,Service与Context无关联

两者都需要在清单文件中注册Service

17. IntentService的使用场景与特点

IntentService是Service的子类,是一个异步的,会自动停止的服务,很好的解决了传统Service中处理完耗时任务玩忘记停止并销毁Service的问题

优点:
一方面不需要自己去new Thread
另一方面不需要考虑在什么时候关闭该Service

18.Android中常见的内存泄漏及解决方案

什么是内存泄漏?
在Android开发中,当一个对象不需要使用了,本该被垃圾回收机制回收,但是另一个正在使用的对象持有它的引用而导致它不能被正常回收,这就导致本该被回收的对象而不能被回收而停留在堆内存中,产生内存泄漏

内存泄漏的影响?

由于Android系统为每个应用程序分配的内存有限,当一个应用产生的内存泄漏比较多时,就会导致应用所需内存超过系统分配内存,造成内存溢出导致应用崩溃。

单例模式造成的内存泄漏
Handler造成的内存泄漏
线程造成的内存泄漏
非静态内部类造成的内存泄漏
资源未关闭造成的内存泄漏

19.Android性能优化

合理管理内存

(1) 节制使用Service ,可以使用IntentService代替Service,当后台任务执行结束后会自动停止,避免了Service的内存泄漏
(2)当界面不可见时释放内存。重写Activity的onTrimMemory()方法,当用户离开当前界面时,可以进行资源释放操作
(3)避免在Bitmap上浪费内存,对大图片进行缩放加载
(4)用SparseArray代替HashMap。HashMap会相对比较低效,因为它需要为每一个键值对都提供一个对象接口,而SparseArray就避免掉了基本数据类型转换成对象数据类型的时间
(5)避免使用依赖注入框架

分析内存的使用情况

可以借助LeakCanary分析内存使用情况

高性能编码优化

(1)如果需要拼接字符串时,优先考虑使用StringBuffer或者StringBuilder来进行拼接,而不是使用加号连接符
(2)常量使用static final 修饰符
(3)使用增强for循环
(4)多使用系统封装好的API

布局优化

(1)避免布局层次嵌套过深,减少布局层次,加快渲染速度
(2) include 标签 重用共同的布局文件
(3)使用merge标签来减少视图层级结构
比如说,主布局是线性布局,include进来的布局也是个线性布局,这时候include进来的线性布局就是多余的,可以用merge标签代替
(4)ViewStub 它是一个轻量级的View,宽和高都为0,实现View的延时加载,避免资源浪费,减少渲染时间,在需要的时候才加载View
(5) TextView 同时显示文字和图片
(6)线性布局自带分割线
(7)使用Space控件,表示占据一定的空间,但是却不显示任何东西

20.RecycleView和ListView的异同

(1)两者都用ViewHolder来保存视图
ListView中,ViewHolder需要自己来定义
RecycleView中ViewHolder是必须存在的

(2)ListVeiw只支持垂直方向上的滚动
RecycleView既可以支持垂直方向上的滑动,也可以支持水平方向上的滑动,还可以支持网格或者网格交叉的瀑布流

(3) ListView中如果要添加item之间的分割线,直接在布局文件中指定divider即可,但是RecycleView不可以

(4)ListView可以直接设置item的点击事件,而RecycleView的点击事件和长按事件需要自己实现

(5)ListView可以设置选择模式,而RecycleView不能

21.Android中的MVC与MVP

MVC

Model层:对应JavaBean、数据库和网络请求
View层:对应xml布局文件、自定义View或者View'Group
Controller层:对应Activity、Fragment

优点:Controller层起到桥梁作用,在View层和Model层之间通信,使得View层和Mode层分离解耦

缺点:随着功能的不断迭代与越来越复杂的交互处理,Controller层也就是Activity、Fragment中的代码越来越多,变得臃肿,难以维护。

MVP

Model层: 对应Java Bean、数据库和网络请求等
View层: 处理数据展示,用户的交互。对应Activity、Fragment
Presenter层: 是Model层和View层的桥梁,从Model层中获取数据,展示在View层

优点:Presenter层负者完成Model层和View层的交互,让Model层和View层完全解耦,代码结构清晰,方便测试
缺点:每个 View 都有 Presenter ,跟其对应的接口,类的数量会明显变多

两者区别

MVC:允许Model和View进行交互

MVP:Model和View进行交互交由Presenter完成,简化了Activity中的代码,将复杂业务逻辑提取到了Presenter中处理,降低了耦合度。方便测试。

22.HashMap和HashTable的主要区别是什么?两者底层的数据结构是什么?

二者都实现了Map接口,是将唯一键映射到特定的值上
主要区别:
(1)HashMap没有排序,允许存入null键和null值;HashTable不允许
(2)HashMap把HashTable的contains方法去掉了,改成containsvalue和containskey
(3)HashTable 继承自Dictionary类,HashMap是java1.2 引进的Map的接口实现
(4)Hashtable是线程安全的,效率低;HashMap是线程非安全的,效率高

HashMap和HashTable的底层实现数据结构:
HashMap和Hashtable的底层实现都是数组+链表结构实现的

23.Java的虚拟机JVM的两个内存:栈内存和堆内存的区别是什么?

Java把内存划分为两种:一种是栈内存,一种是堆内存。两者区别是:
(1)栈内存:在函数中定义的一些基本类型变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间。

(2) 堆内存:堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理

24.volatile和synchronized区别

在Java中,为了保证多线程读写数据时保证数据的一致性,可以采用两种方式:
(1)使用synchronized关键字
(2)使用volatile关键字:volatile能够使变量在发生改变时能尽快地让其他线程知道

两者的区别:
(1)volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住
(2)volatile仅能使用在变量级别,synchronized则可以使用在变量,方法
(3)volatile仅能实现变量的修改可见性,而synchronized则可以保证变量的修改可见性和原子性
(4)volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞

25.SpaseArray 和HashMap

SparseArray比HashMap更省内存,性能更好。主要是因为SparseArray避免了对key的自动装箱,它内部通过2个数组来进行数据存储的,一个存储key,一个存储Value。SparseArray内部对数据采取了压缩的方式来处理数据,节省内存空间。
SparseArray在存储和读取数据的时候采用的是二分查找法,效率高,而HashMap获取数据是通过遍历数组来得到对应的元素。

26.重载和重写的区别

重载:允许存在一个以上的同名函数,只要它们的参数类型不同即可
重写:当子类继承父类,沿袭了父类的功能到子类中,子类虽具备该功能,但功能内容不一致,这是使用覆盖特性,保留父类的功能定义,并重写功能内容

27.单例模式


//懒汉模式
public class SingleInstance
{
    //私有构造函数,防止通过构造器创建对象
    private SingleInstance(){}
    
    private static SingleInstance instance = null;
    
    public static SingleInstance getInstance(){
        if(instance == null){
            instance = new SingleInstance();
        }
        return instance;
    }
}

//饿汉模式,类加载时就已经进行实例化,类加载较慢,但获取对象速度快,线程安全
public class SingleInstance {
    //私有构造函数,防止通过构造器创建对象
    private SingleInstance() {}

    private static final SingleInstance instance = new SingleInstance();

    public static SingleInstance getInstance() {
        return instance;
    }
}


28.AsyncTask

AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新ui。

AsyncTask内部封装了Thread和Handler,AsyncTask并不适合执行特别耗时的任务

AsyncTask是一个抽象的泛型类,它提供了Params、Progress、Resault这三个泛型参数

实现了4个核心方法:

(1)onPreExecute() 在主线程中执行,在异步任务执行之前,此方法会被调用,一般可以用于做一些准备工作

(2)doInBackground() 在线程池中执行,此方法用于执行异步任务。在这个方法中通过publishProgress方法来更新任务的进度

(3)onProgressUpdate() 在主线程中使用,当后台任务的执行进度发生改变时此方法会被调用

(4)onPostExecute(Resault resault) 在主线程中使用在异步任务执行之后,次方法会被调用,其中resault 参数是后台任务的返回值

Asynctask在使用过程中有一些条件限制:
(1) AsyncTask类必须在主线程中加载,AsyncTask对象必须在主线程中创建
(2)execute方法必须在UI线程中调用
(3)一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否者会报运行时异常
(4) Android1.6之前:串行执行任务 ,Android1.6-Android3.0 :并行执行任务 ,Android3.0之后 :串行执行任务

29. Arraylist和linkedlist、Vector的区别

(1) Arraylist是基于数组的数据结构
特点:查询速度快,但是增删速度慢,线程不同步,效率高
(2) LinkedList:底层使用的是链表数据结构
特点:增删速度很快,查询速度慢
(3) Vector: 底层是数组数据结构,线程同步,效率低,被ArrayList替代了

30. HashTable和HashMap

(1) HashTable 底层是哈希表数据结构,不可以存入null键和null值,该集合是线程同步的,效率低
(2) HashMap 底层是哈希表数据结构,允许存入null键和null值,线程不同步,效率高

31.自定义控件

(1)自定义view属性
(2)重写构造方法,在构造方法使用TypeArray获取自定义属性值
(3)重写onDraw方法,将view绘制到画布上
(4) 重写onMeasure()方法,将view重新布局

32. 线程与进程

线程是CPU调度的最小单元,同时线程是一种有限的系统资源
进程是指一个执行单元,在PC和移动设备上指一个程序或者一个应用
一个进程可以包含多个线程,进程和线程是包含和被包含的关系

33. Bitmap的高效加载

主要是采用BitmapFactory.Options来加载所需尺寸的图片,通过BitmapFactory.Options可以按一定的采样率来加载缩小后的图片,将缩小的图片在Imageview上显示,降低内存,在一定程度上避免OOM.

通过BitmapFactory.Options来缩放图片,主要用到了inSampleSize参数,即采样率。例如,当inSampleSize = 2时,那么采样后的图片宽和高均为原图的1/2,像素为原图的1/4,占用内存大小也为原图的1/4

34. View的事件分发机制

当点击事件产生后,首先它的dispatchTouchEvent就会被调用,如果ViewGroup的onInterceptTouchEvent方法返回true就表示它要拦截当前事件,接着事件就会交给这个ViewGroup来处理,即它的onTouchEvent方法就会被调用;如果这个ViewGroup的onInterceptTouchEvent返回false就表示它不拦截当前事件,这时当前事件就会继续传递给它的子元素,接着子元素的dispatchTouchEvent方法就会被调动,如此反复直到事件被最终处理。

你可能感兴趣的:(面试相关)