2017年面试问题总结

第一家公司

  • 1:如果最快的获取控件的宽高?
    答:三种方法
    1) 方法一 (此方法会加载onMeasure三次)
       int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);  
        int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);  
        imageView.measure(w, h);  
        int height =imageView.getMeasuredHeight();  
        int width =imageView.getMeasuredWidth();  
        textView.append("\n"+height+","+width);  
       ```
2)    方法二(此方法会加载onMeasure二次,但是回调函数会回调很多次  )

ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
textView.append("\n"+height+","+width);
return true;
}
});

3)    方法三(此方法会加载onMeasure二次,但是回调函数只回调一次)

ViewTreeObserver vto2 = imageView.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth());
}
});

- 2:View的分发机制?
具体请查看[Android View相关知识总结](http://www.jianshu.com/p/91fa8faa6925)

- 3: invalidate()和postInvalidate()的使用与区别?
  Android中实现view的刷新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。
   Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用
**利用invalidate()刷新界面**
  实例化一个Handler对象,并重写handleMessage方法调用invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。
**使用postInvalidate()刷新界面**
   使用postInvalidate则比较简单,不需要handler,直接在工作线程中调用postInvalidate即可
- 4:多线程原理?

第二家公司
- 1:图片的三级缓存?
   内存-文件-网络三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结构中。当根据url向网络拉取图片的时候,先从内存中找,如果内存中没有,再从缓存文件中查找,如果缓存文件中也没有,再从网络上通过http请求拉取图片。在键值对(key-value)中,这个图片缓存的key是图片url的hash值,value就是Bitmap。所以,按照这个逻辑,只要一个url被下载过,其图片就被缓存起来了。
  - **1)、内存缓存**
  Java中对象的四种引用类型介绍
  强引用
  Java中所有new出来的对象都是强引用类型,回收的时候,GC宁愿抛出OOM异常,也不回收它。

Map mImageCache = new HashMap<>();

  软引用,SoftReference
  内存足够时,不回收。内存不够时,就回收。这里使用这种方式缓存对象。

Map> mImageCache = new HashMap<>();

  弱引用,WeakReference
  GC一出来工作就回收它。
  虚引用,PhantomReference
  用完就消失。
** 使用LruCache类来做缓存**
  LruCache其实是一个Hash表,内部使用的是LinkedHashMap存储数据。使用LruCache类可以规定缓存内存的大小,并且这个类内部使用到了最近最少使用算法来管理缓存内存。

LruCache> mImageCache = new LruCache<>(1024 * 1024 * 4);

第三家公司
- 1:Dagger2原理?

第四家公司
- 1:Service是否在主线程执行?
  service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。
- 2:bindService和startService区别?
  执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Service会一直在后台运行,下次调用者再起来仍然可以stopService。
  执行bindService时,Service会经历onCreate->onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy。这里所谓的绑定在一起就是说两者共存亡了。
  多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。Service的onStart方法在API 5时被废弃,替代它的是onStartCommand方法。
  第一次执行bindService时,onCreate和onBind方法会被调用,但是多次执行bindService时,onCreate和onBind方法并不会被多次调用,即并不会多次创建服务和绑定服务。
- 2:内存溢出和内存泄漏有什么区别?
  内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
  内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!

你可能感兴趣的:(2017年面试问题总结)