Android面试总结(持续更新)

主要分为android和java。

一、Android

1、Fragment传值。setArgument或者在onAttach中获取接口。

2、commit和commitAllowingStateLoss的区别。commit在onSaveInstanceState()之前调用,commitAllowingStateLoss在onSaveInstanceState()之后调用。

3、ListView的复用机制。每个viewType对应一个RecycleBin。所有不在屏幕上的item都缓存在RecycleBin。

4、viewpager中的Fragment怎么判断是否用户可见。setUserVisibleHint或者PagerSelectListener

5、onMeasure方法作用。测量大小并告诉父控件。

6、inflate各个参数。第一个参数略,第二个参数是父布局,第三个参数是是否放进父布局。

参考:https://blog.csdn.net/u012702547/article/details/52628453

7、followLayout。onMeasure函数里面存储临时变量w、h。遍历每一个child,Measure他们的宽度,如果总w达到最大值,就把这个child放在下一行,增加一个h。按照onMeasure里面的方案在onLayout里面放置每一个child。

8、事件分发机制。略。

9、圆形图片怎么做。对bitmap或者imageView的onDraw进行操作,drawBitmap时传入一个圆形的渲染器(shader)

protected void onDraw(Canvas canvas) {

        mPaint = new Paint();

        Drawable drawable = getDrawable();

        if (null != drawable) {
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

        //初始化BitmapShader,传入bitmap对象
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        //计算缩放比例
        mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());

        Matrix matrix = new Matrix();
        matrix.setScale(mScale, mScale);
        bitmapShader.setLocalMatrix(matrix);
        mPaint.setShader(bitmapShader);
        //画圆形,指定好坐标,半径,画笔
        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
        } else {
            super.onDraw(canvas);
        }
    }

10、本地图片预览(高分辨率的图片怎样处理)

 public static Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        //避免出现内存溢出的情况,进行相应的属性设置。
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        options.inDither = true;

        return BitmapFactory.decodeFile(filePath, options);
    }

11、Retrofit的优点。略

12、Activity四种启动方式。standard。singleTask:ABC再开B会关掉C,B回调onNewIntent。singleInstance:新栈,栈里只有他。singleTop:栈顶再开一次,调onNewIntent

13、LeakCanary。在被监控的页面加一个变量,看他的回收情况。

14、apk打包流程

 

  1. 通过AAPT工具进行资源文件(包括AndroidManifest.xml、布局文件、各种xml资源等)的打包,生成R.java文件。
  2. 通过AIDL工具处理AIDL文件,生成相应的Java文件。
  3. 通过Javac工具编译项目源码,生成Class文件。
  4. 通过DX工具将所有的Class文件转换成DEX文件,该过程主要完成Java字节码转换成Dalvik字节码,压缩常量池以及清除冗余信息等工作。
  5. 通过ApkBuilder工具将资源文件、DEX文件打包生成APK文件。
  6. 利用KeyStore对生成的APK文件进行签名。
  7. 如果是正式版的APK,还会利用ZipAlign工具进行对齐处理,对齐的过程就是将APK文件中所有的资源文件举例文件的起始距离都偏移4字节的整数倍,这样通过内存映射访问APK文件 的速度会更快。

15、android的handler的机制是什么

  1. Handler通过sendMessage()发送消息Message到消息队列MessageQueue。
  2. Looper通过loop()不断提取触发条件的Message,并将Message交给对应的target handler来处理。
  3. target handler调用自身的handleMessage()方法来处理Message。

二、Java

1、synchronized

2、堆和栈。堆是进程共享的;一个线程一个栈,执行一个方法创建一个栈帧,栈帧负责存储局部变量变量表、操作数栈、动态链接和方法返回地址等信息。

3、GC

一般说来,我们要解决一些三个问题:

  • 哪些内存回收?
  • 什么时候回收?
  • 如何回收?

这些问题分别对应着引用管理和回收策略等方案。

提到引用,我们都知道Java中有四种引用类型:

  • 强引用:代码中普遍存在的,只要强引用还存在,垃圾收集器就不会回收掉被引用的对象。
  • 软引用:SoftReference,用来描述还有用但是非必须的对象,当内存不足的时候回回收这类对象。
  • 弱引用:WeakReference,用来描述非必须对象,弱引用的对象只能生存到下一次GC发生时,当GC发生时,无论内存是否足够,都会回收该对象。
  • 虚引用:PhantomReference,一个对象是否有虚引用的存在,完全不会对其生存时间产生影响,也无法通过虚引用取得一个对象的引用,它存在的唯一目的是在这个对象被回收时可以收到一个系统通知。

不同的引用类型,在做GC时会区别对待,我们平时生成的Java对象,默认都是强引用,也就是说只要强引用还在,GC就不会回收,那么如何判断强引用是否存在呢?

一个简单的思路就是:引用计数法,有对这个对象的引用就+1,不再引用就-1,但是这种方式看起来简单美好,但它却不嫩解决循环引用计数的问题。

因此可达性分析算法登上历史舞台,用它来判断对象的引用是否存在。

可达性分析算法通过一系列称为GC Roots的对象作为起始点,从这些节点从上向下搜索,搜索走过的路径称为引用链,当一个对象没有任何引用链 与GC Roots连接时就说明此对象不可用,也就是对象不可达。

GC Roots对象通常包括:

  • 虚拟机栈中引用的对象(栈帧中的本地变量表)
  • 方法去中类的静态属性引用的对象
  • 方法区中常量引用的对象
  • Native方法引用的对象

可达性分析算法整个流程如下所示:

  1. 第一次标记:对象在经过可达性分析后发现没有与GC Roots有引用链,则进行第一次标记并进行一次筛选,筛选条件是:该对象是否有必要执行finalize()方法。没有覆盖finalize()方法或者finalize()方法已经被执行过都会被 认为没有必要执行
    • 如果有必要执行:则该对象会被放在一个F-Queue队列,并稍后在由虚拟机建立的低优先级Finalizer线程中触发该对象的finalize()方法,但不保证一定等待它执行结束,因为如果这个对象的finalize()方法发生了死循环或者执行 时间较长的情况,会阻塞F-Queue队列里的其他对象,影响GC。
  2. 第二次标记:GC对F-Queue队列里的对象进行第二次标记,如果在第二次标记时该对象又成功被引用,则会被移除即将回收的集合,否则会被回收。

4、内存分代GC

  • 为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation)3个区域
  • 新生代分别是Edne和Survivor组成,Survivor里面分S0和S1
  • 大多数情况下,对象在Eden中分配,当Eden没有足够空间时,会触发一次Minor GC
  • 当新生代发生GC(Minor GC)时,会将存活的对象移动到S0内存区域,并清空Eden区域,当再次发生Minor GC时,将Eden和S0中存活的对象移动到S1内存区域。
  • 存活对象会反复在S0和S1之间移动,当对象从Eden移动到Survivor或者在Survivor之间移动时,对象的GC年龄自动累加,当GC年龄超过默认阈值15时,会将该对象移动到老年代
  • 老年代的空间大小即-Xmx 与-Xmn 两个参数之差,用于存放经过几次Minor GC之后依旧存活的对象。当老年代的空间不足时,会触发Major GC/Full GC,速度一般比Minor GC慢10倍以上。

三、框架
1、TCP与UDP的差别

  • TCP面向链接,UDP是无连接的。
  • TCP提供可靠的服务。也就是说TCP提供的服务无差错、不丢失、不重复,且按需到达。UDP尽最大努力交付,即不保证交付。
  • TCP面向字节流,实际上TCP是把数据看成一段无结构的字节流;UDP面向报文的,UDP没有拥塞控制,因此网络出现拥塞也不会使源主机的发送速率降低(对实时应用很有效,如IP电话、实时视频会议等)
  • 每一条TCP都是点对点的;UDP支持一对一,一对多和多对多的交互通讯。
  • TCP的首部开销是20字节。UDP的首部开销是8字节。
  • TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。

2、三次握手和四次分手,略。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Android)