经典面试题(不断更新中)

——————————————————————–史上最强面试题————————————————————————————-

AIDL

1、 要使用AIDL的前提的条件我们要只知道它是干什么的?
    #AIDL 也就是在Android中定义的一个语言,他是进行进程间通讯的一种实现方式,通过定义AIDL接口,可以实现进程间通讯机制
2、 要知道它的使用步骤,前提条件??
    #需求:比如现在有2个进程需要通信,那么他们是怎么进行通讯,使用步骤是什么??一个A,一个是B,B要用A里面的服务;
    1)、首先在A中写一个服务,在服务里面定义一个方法进行暴露出去 ;
    2)、刚刚我们说了要将这个方法暴露出去那么怎么暴露出去,现在就要用到AIDL来实现进程间通讯的机制了 ;
    3)、定义一个接口.把要暴露的方法定义在接口中,不要有public之类的修饰符,不然会报错!,然后把这个接口的后缀名改为aidl格式 ;系统会自动在gen生成二个文件其中有一个是以接口名字.java命名的
    4)、在A服务中定义一个中间人对象,写一个类继承Stub(实现接口它的本身已经已经实现了我们AIDL接口语言)实现暴露出去的方法.
    5)、现在B中想要调用A中的服务,那么就可以通过我们刚刚写的AIDL来实现2个进程间的通信,把A中的AIDLCody到B的SRC目录下
    6)、通过BindService绑定到A中的服务,然后在bindService里面创一个服务连接成功的接口,
    7)、写一个类实现ServiceConnection,里面有连接成功和失败的方法,我们现在就可以在连接成功的时候通过Stub这个对象里面的asInterface这个方法可以获取到中间人对象,
    8)、现在有中间人这个对象你就可以对A里面任意操作了,因为已经建立起关系了;

Handler

首先要知道Handler是干什么用的??
1、要明白Handler,Looper,MesagerQuque,Mesager三者的关系
    1). Mesager 是消息的意思那么它的消息是通过MesagerQueque来进行维护消息的;
    2). MesagerQuque 是消息队列的意思,消息最终会进行这个里面,是以发送的时间顺序进行以链表的形式进入消息队列的;
    3). Handler 这个是个重要角色 他是进行处理消息和发送消的关键所在,跟Looper建立起联系的
    4). Looper 自身具备循环机制,是不断重消息队列里面取消息的;
2、明白当在子线程发送消息的是怎么在主线程中收到消息的
    1)当我们在主线程创建一个Handler对象会进入Handler的构造方法,构造方法里面有一个Looper.myLooper对象,当我们点击进去发现有一个当前线程get方法,那么有get就有set,set方法里面创建一个了一个Looper对象,looper对象里面会创建一个消息队列,现在有了消息对列,那消息是怎么进入到我这个消息队列里面的??又是怎么出去的???
    2). 消息入队,enqueueMessage就是消息队列的里面的方法,它就是进行入队的,那么是怎么入队了,因为当我们不管是通过Handler.XXX发送消息最终都会都到sendMesagerAtTime方法,然后消息对象是以时间进行排序进入消息对列里面,现在我们知道消息怎么进入队列,哪消息怎么出去了??
    3). 消息出队,是在Looper.loop里面Looper对象.消息队列,通过next取出消息,一直是死循环取消息,这里有可能会造成线程阻塞,为什么会造成阻塞(有可能又在主线程中做耗时的操作了),现在知道消息的入队和出队了  那么怎么消息就跑到主线程了
    4). 刚刚在Looper.loop()里面取完消息的时候就会mes.tager.dispatchMessage(msg);把消息分发出去.tager就代表发送消息的handler;
    5). 刚刚在Looper里面分发完消息,现在就回到Handler.dispatchMessage(),通过看先消息自身的回调如果不等于null的话,就调用自身的run方法,否则调用Callback中的handleMessage,如果前面都不满足的话  ,最后才调用Handler自身的HandlerMeaaseger方法更新UI

自定义控件

1、明白继承View的流程
    1). 自定义View的属性
    2). 在View的构造方法中获取我们自定义的属性
    3). 重写onMesure
    4). 重写onDraw

Android中的设计模式

1. 明白单列的好处???
    1). 避免创建多个对象,占用内存空间
  明白创建单列模式有哪些方式???
    1). 我喜欢用内部类的形式
        好处: 节省内存,线程安全
    2). 双重锁懒汉式  安全  但是效率不好
    单例模式

定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,让外部来访问这个类的唯一实例。
饿汉式:  private static Singleton uniqueInstance = new Singleton(); 
懒汉式  private static Singleton uniqueInstance = null; 
功能

单例模式是用来保证这个类在运行期间只会被创建一个类实例,另外,单例模式还提供了一个全局唯一访问这个类实例的访问点,就是getInstance方法。

范围

Java里面实现的单例是一个虚拟机的范围。因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoader装载饿汉式实现单例类的时候就会创建一个类的实例。

懒汉式单例有延迟加载和缓存的思想

优缺点

懒汉式是典型的时间换空间
饿汉式是典型的空间换时间
不加同步的懒汉式是线程不安全的。比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,就可能导致并发问题。

饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。

如何实现懒汉式的线程安全?

加上synchronized即可

public static synchronized Singleton getInstance(){}
但这样会降低整个访问的速度,而且每次都要判断。可以用双重检查加锁。

双重加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例。这是第二重检查。

双重加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。


/**
 * 双重检查加锁的单例模式
 * @author dream
 *
 */
public class Singleton {

/**
 * 对保存实例的变量添加volitile的修饰
 */
private volatile static Singleton instance = null;
private Singleton(){

}

public static Singleton getInstance(){
    //先检查实例是否存在,如果不存在才进入下面的同步块
    if(instance == null){
        //同步块,线程安全的创建实例
        synchronized (Singleton.class) {
            //再次检查实例是否存在,如果不存在才真正的创建实例
            instance = new Singleton();
        }
    }
    return instance;
}

}

一种更好的单例实现方式

public class Singleton {

/**
 * 类级的内部类,也就是静态类的成员式内部类,该内部类的实例与外部类的实例
 * 没有绑定关系,而且只有被调用时才会装载,从而实现了延迟加载
 * @author dream
 *
 */
private static class SingletonHolder{
    /**
     * 静态初始化器,由JVM来保证线程安全
     */
    private static final Singleton instance = new Singleton();
}

/**
 * 私有化构造方法
 */
private Singleton(){

}

public static Singleton getInstance(){
    return SingletonHolder.instance;
}

}

根据《高效Java第二版》中的说法,单元素的枚举类型已经成为实现Singleton的最佳方法。

package example6;

/**
 * 使用枚举来实现单例模式的示例
 * @author dream
 *
 */
public class Singleton {

/**
 * 定义一个枚举的元素,它就代表了Singleton的一个实例
 */
uniqueInstance;

/**
 * 示意方法,单例可以有自己的操作
 */
public void singletonOperation(){
    //功能树立
}
}

本质

控制实例数量

何时选用单例模式

当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式,这些功能恰好是单例模式要解决的问题。
2. 适配器模式:ListView,GridView的Adapter
    1). 简介: 不同的数据提供使用一个适配器来想一个相同的客服提供服务
3. 建造者模式:AlertDialog.Builder
    1). 简介: 可以分步地构造每一部分.
4. 享元模式:Message.obtainMessage通过Message对象来避免大量的Message对象被频繁的创建和销毁
    1). 运用共享技术有效的支持大量细粒度的对象
5. 命令模式: Handler.post后Handler.handlerMessage
    1). 简介: 把请求封装成一二对象发送出去,方便定制、排队、取消.
6. 迭代器模式: 如通过Hashtable.elements方法可以得到一个Enumeration,然后通过这个Enumeration访问Hashtable中的数据,而不用关心Hashtable中的数据存放方式
    1). 提供一个方法顺序访问数据集合中的所有数据而又不暴露对象的内部表示
7. 备忘录模式:Activity的onSaveInstanceState和onRestoreInstanceState就是通过Bundle这种序列化的数据结构来存储Activity的状态,至于其中存储的数据结构,这两个方法不用关心
    1). 简介: 不需要了解对象的内部结构的情况下备份对象的状态,方便以后恢复
8. 观察者模式: 我们可以通过BaseAdapter.registerDataSetObserver和BaseAdapter.unregisterDataSetObserver两方法来向BaseAdater注册、注销一个DataSetObserver。这个过程中,DataSetObserver就是一个观察者,它一旦发现BaseAdapter内部数据有变量,就会通过回调方法DataSetObserver.onChanged和DataSetObserver.onInvalidated来通知DataSetObserver的实现类。事件通知也是观察者模式
    1). 简介:一个对象发生改变时,所有信赖于它的对象自动做相应改变。
9. 原型模式:比如我们需要一张Bitmap的几种不同格式:ARGB_8888、RGB_565、ARGB_4444、ALAPHA_8等。那我们就可以先创建一个ARGB_8888的Bitmap作为原型,在它的基础上,通过调用Bitmap.copy(Config)来创建出其它几种格式的Bitmap。另外一个例子就是Java中所有对象都有的一个名字叫clone的方法,已经原型模式的代名词了
    1). 简介:在系统中要创建大量的对象,这些对象之间具有几乎完全相同的功能,只是在细节上有一点儿差别。
10. 状态模式:View.onVisibilityChanged方法,就是提供了一个状态模式的实现,允许在View的visibility发生改变时,引发执行onVisibilityChanged方法中的动作。
    1). 简介:状态发生改变时,行为改变。
11. 策略模式:
    举例:Java.util.List就是定义了一个增(add)、删(remove)、改(set)、查(indexOf)策略,至于实现这个策略的ArrayList、LinkedList等类,只是在具体实现时采用了不同的算法。但因为它们策略一样,不考虑速度的情况下,使用时完全可以互相替换使用。
    1). 简介: 定义了一系封装了算法、行为的对象,他们可以相互替换.
12. 调解者模式
    简介:一个对象的某个操作需要调用N个对象的M个方法来完成时,把这些调用过程封装起来,就成了一个调解者
    举例:如Resource.getDrawable方法的实现逻辑是这样的:创建一个缓存来存放所有已经加载过的,如果getDrawable中传入的id所对应的Drawable以前没有被加载过,那么它就会根据id所对应的资源类型,分别调用XML解析器生成,或者通过读取包中的图片资源文件来创建Drawable。而Resource.getDrawable把涉及到多个对象、多个逻辑的操作封装成一个方法,就实现了一个调解者的角色。
12. 抽象工程模式
    DAO与Service的使用

大图片造成的OOM是怎么解决的

1、通过压缩的方式,具体怎么压缩??
    直接使用ImageView显示bitmap会占用较多资源,特别是图片较大的时候,可能导致崩溃。 
    使用BitmapFactory.Options设置inSampleSize, 这样做可以减少对系统资源的要求。 
    属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。 

    BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();  
    bitmapFactoryOptions.inJustDecodeBounds = true;  
    bitmapFactoryOptions.inSampleSize = 2;  
    // 这里一定要将其设置回false,因为之前我们将其设置成了true    
    // 设置inJustDecodeBounds为true后,decodeFile并不分配空间,即,BitmapFactory解码出来的Bitmap为Null,但可计算出原始图片的长度和宽度    
    options.inJustDecodeBounds = false;  
    Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap, options);  

2、通过LRU缓存的方式,具体怎么实现的??
    指定内存空间,我们自己分分配缓存大小

项目中MVC用到的多吗??都代表什么意思??

目前项目中用的基本上都是MVC 因为MVC模式它是将视图和数据,逻辑代码都剥离了出来,这样做的效果就是便于以后添加功能比较方便,便于维护
M:Model   负责处理数据  比如javaBean,联网处理,
V:View    处理界面展示结果的 XML
C:Controller  控制器  就是起桥梁作用,负责Model,View层数据之间的通信
好处: 便于后期维护和添加新功能
缺点: 它的首要职责是加载应用的布局和初始化用户的界面,并接受来自用户的操作请求,进而做响应.Activty类的职责不断增加,以致变得庞大臃肿.

大概说一下MVP???

M: model提供数据
V: 负责显示
P: 负责逻辑处理

MVC与MVP之前的区别???

View与Model并不直接交互,而是通过与Presenter交互来与Model直接交互
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑,而Controller是基于行为的,并且可以被多个View共享,Controller可以负责决定显示那个View

将一讲你在项目中线程池用的多吗???

将一讲你在项目中对象池用的多吗(听都听不懂)???

ArrayList(集合里面有1~100的数,怎么用2种方法可以使偶数去重)

怎么读取N个大文件效率怎么最高(思路:创建多个线程);

反射(你在项目中用的多吗,具体谈谈)

1). fromName(全类名);(读取配置文件)
2). 类名.Class();(当做静态方法的锁对象)
3). 对象名.getClass();(判断是不是同一个字节码对象)

Android属性动画怎么获取变化中的ARGB值(利用ValuesAnimontor)

通过属性动画中的值动画添加一个监听器通过监听器中的对象名获取变化中的值

事件传递机制(将一讲事件处理,如果都不要事件,最后事件都被谁消费了)

ListView Item上面有一个Button,当我点击ListView的时候,Button把事件抢走了,这怎么处理啊?

购物车中增加物品数量逻辑怎么实现

getMeasuredWidth与getWidth区别

1). getMeasuredWidth方法获得的值是setMeasuredDimension方法设置的值,它的值在measure方法运行后就会确定
2). getWidth方法获得是layout方法中传递的四个参数中的mRight-mLeft,它的值是在layout方法运行后确定的
3). 一般情况下在onLayout方法中使用getMeasuredWidth方法,而在除onLayout方法之外的地方用getWidth方法。

Service中的onStartCommand和onStart()方法有什么区别???

1). 在Android API 2.0 之后 实现onStart等于实现了onStartCommand()方法;
2). 在AndroidAPI  2.0之后onStart()被onStartCommand()方法取代了;
3). 无论何时, 都会先调用onStartCommand(),在调用onStart()。    
注意:onStartCommand()方法必须返回一个整数,这个整数是一个描述了在系统的杀死事件中,系统应该如何继续这个服务的值(虽然你能够修改这个值,但是IntentService处理还是为你提供了默认实现)。从onStartCommand()方法中返回的值必须是以下常量:    
1. START_NOT_STICKY
如果系统在onStartCommand()方法返回之后杀死这个服务,那么直到接受到新的Intent对象,这个服务才会被重新创建。这是最安全的选项,用来避免在不需要的时候运行你的服务。
2. START_STICKY
如果系统在onStartCommand()返回后杀死了这个服务,系统就会重新创建这个服务并且调用onStartCommand()方法,但是它不会重新传递最后的Intent对象,系统会用一个null的Intent对象来调用onStartCommand()方法,在这个情况下,除非有一些被发送的Intent对象在等待启动服务。这适用于不执行命令的媒体播放器(或类似的服务),它只是无限期的运行着并等待工作的到来。
3. START_REDELIVER_INTENT
如果系统在onStartCommand()方法返回后,系统就会重新创建了这个服务,并且用发送给这个服务的最后的Intent对象调用了onStartCommand()方法。任意等待中的Intent对象会依次被发送。这适用于那些应该立即恢复正在执行的工作的服务,如下载文件。

Http协议

协议就是字段和格式描述的文档
1). 字段
    帮助辨识数据的含义
2). 格式 : 帮助将数据归类
    JSON : 数据格式简单,数据精简,节约数据流量
    XML  : 格式良好,复杂,耗费流量但是扩展性好

TCP/IP协议

IP: 就是每台电脑上的IP地址,端口用于查找电脑运行的应用;
TCP:用于传输数据的
    TCP:面向连接,三次握手,是稳定的传输协议
    UDP:面向无连接,数据不安全,传输的数据有可能丢失

事件分发机制

1). 点击屏幕的时候触发Activity的onTouch()事件,当Activity接收到触摸事件的时候,将遍历子View进行Down事件分发ViewGroup可以看做是递归的,分发事件的目的就是要看是哪个子View需要Down事件,如果需要就在子View的onTouchEvent()方法中放回true,事件将有它消费,不在进行分发;
2). 当ViewGroup中所有子View都不需要Down事件的话,最终事件会调用父类View的dispatchTouchEvent(),在所有子View都不处理的情况下,会调用Activity本身的onTouch()方法;

2016/9/29

onClick()怎么处理??

1). btn1.setOnClickListener(new OnClickListener())
2). Xml布局中定义"onClick"
3). 让当前类实现onClickListener();
4). btn_call.setOnClickListener(new MyOnClickListener());

OOM与泄露区别??leakcanary

1.内存溢出 out of memory
是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
2.内存泄露 memory leak
是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
3.二者的联系
内存泄露最终会导致内存溢出    

内存溢出(00M)
    内存溢出是指当对象的内存占用已经超出内存的控件大小,这时未经处理
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值