Android面试笔记六:租租车

2019-07-21 22:56 评论 0 条

摘要:

  • 关于JVM:懒汉式单例、饿汉式单例和静态内部类单例有什么区别?
  • 关于JVM:Java虚拟机有自动垃圾回收机制,为什么还会出现内存泄露?内存泄露和OOM有什么关系?
  • Fragment和View有什么区别,为什么使用Fragment?
  • Fragment和Activity有什么区别,为什么使用Fragment?
  • Fragment挂载的Activity销毁后,Fragment是否还存在?
  • 在Activity的onCreate方法中使用Handler延时5s执行DialogFragment.show()代码,这时候按下Home键会怎样?
  • 判断一条单链表是否成环,代码实现
  • 说一下View包含哪些生命周期
  • 一个apk由哪几个文件夹组成以及每个文件夹的作用?
  • Kotlin比Java有什么优势?
  • Service更新UI,有哪几种方式
  • 有60张1920x1080的图片做成滚动动画效果,一秒内播放15张,如何保证流畅性?

问题一

这是一道深入理解虚拟机的题目,类被虚拟机加载阶段,会将二进制流中的静态存储结构转换成方法区的运行时数据结构,在内存中生成代表这个类的java.lang.Class对象,作为访问这个类的各种数据的入口。类的准备阶段为类变量分配内存并设置类变量的初始值,使用的内存将在方法区进行分配。

  • 饿汉式单例,是一个静态的存储结构,类被加载后在准备阶段类变量被分配内存,遇到new关键字完成初始化,初始化是在类被加载的过程中。饿汉式的特点:线程安全的,类在加载过程分配了内存,速度更快。如果某些单例实际没有被使用到,这种创建单例方式会造成额外的内存开销。
  • 懒汉式单例,调用getInstance()方法开始完成初始化,初始化是在类的构造方法中,是非线程安全的,在初始化内容较多的情况下,可能造成延时,同时在调用的时候分配堆内存,减少内存的浪费。
  • 静态内部类单例,和懒汉式类似,在调用的时候开始分配内存,减少内存的浪费。区别:静态内部类是线程安全的

问题二

垃圾收集器常用的算法有:计数收集器,追踪收集器,压缩收集器,拷贝收集器,按代收集的收集器,自动收集器等,能够被收集的对象需要满足一定的规则,比如:不再持有强引用,将引用置null,一个对象在销毁前还被引用,垃圾收集器认为这是活动的对象,无法满足算法规则,造成内存泄露。

过多的内存泄露会造成内存溢出。

自动垃圾回收机制,需要编程人员写书更符合算法的代码,降低内存销毁,避免内存泄露,同时也要注意频繁地垃圾回收也可能造成额外的性能开销,内存抖动。

问题三

  • Fragment和View都需要挂载到Activity中,不能独立存在
  • Fragment和View拥有各自的生命周期,Fragment的生命周期更丰富,比如:onAttach(Context)onCreate()onCreateView()onViewCreated()onActivityCreate()
  • Fragment实例化后可以添加到回退栈中,使用addToBackStack()方法后,Fragment不会被销毁
  • Fragment可以获取界面之间跳转传递的通信信息,比如:Activity跳转,Fragment切换
  • Fragment应用于碎片化处理,组合成一个大屏幕,每个Fragment负责独立的功能模块,方便管理和方便复用
  • Fragment提供更丰富的方法管理视图交换,比如:onHiddenChanged()setUserVisibleHint(boolean)
  • Fragment通过事务操作,保证操作的原子性,提供丰富的方法:replace()remove()add()hide()show()attach()detach()
  • Fragment用于各种更复杂的界面交互,简单的界面使用View
  • Fragment在Activity异常退出(旋转屏幕),重启后创建新的FragmentManager,并获取保存下来的Fragment队列,恢复保存的状态信息
  • View是无状态的,Activity异常退出(旋转屏幕),View需要重新初始化;
  • View中用户交互、界面更新等相关代码全部写到Activity中,想得臃肿,不方便扩展
  • View和Activity同生死,Fragment在创建后,Activity退出依然存活

问题四

  • Fragment方便被多个Activity复用
  • Fragment初始化占据的内存比Activity少,初始化后响应速度更快
  • Fragment可以用来代替Activity,反之则不可以
  • Fragment模块化管理,降低耦合度,方便UI更新和扩展
  • Fragment初始化后,添加到回退栈,方便重用
  • Fragment提供更新丰富的事务操作方法:replace()remove()add()hide()show()
  • Fragment可以添加到布局文件中,也可以在代码中动态使用,Activity则不可以
  • Fragment使用不需要在清单文件中配置组件信息
  • Fragment搭载ViewPager、TabHost实现更丰富的界面效果
  • Fragment不可以在后台运行,Activity销毁后,创建的Fragment仍可以存活,这时候需要注意getActivity()返回null
  • Fragment在异常退出(旋转屏幕),Fragment被销毁,可以保存状态信息,重启后可以恢复原来的状态

问题五

Fragment执行onAttach()方法挂载到Activity中,Activity销毁后执行onDetach()解除挂载,这时候已创建的Fragment不会仍然存活。

重启Activity后,创建新的FragmentManager,并获取保存下来的Fragment队列,恢复保存的状态信息

这样,避免重复创建Fragment的内存开销。

问题六

Fragment无法在后台运行。

Activity初始化后,按钮Home键,Activity进入了后台,这个时候延时5s执行DialogFragment.show()方法,会崩溃退出!

原因:Fragment无法在后台运行,Activity进入后台后,Fragment无法执行其完整的生命周期方法,比如:onAttach()onCreate(),这时候执行DialogFragment.show,程序会异常退出。

问题七

Node表示一条单链表,这里省略了单例的创建过程,详情参考《Java常用数据结构》,识别是否成环的核心代码:

boolean loopSingleList(Node node){
    //如果node为null或下一个节点为null,非循环链表
    if(node==null||node.next==null) return false;
    Node p1=node;
    Node p2=node;
    Node last=null;
    while((last=p2.next)!=null&&(last.next!=null)){
        p1=p1.next;//每次移动一步
        p2=last.next;//每次移动两步
        if(p1==p2) return true;//p1等于p2,成环
        return false;//默认不成环
    }
}

问题八

View的生命周期包括:创建、挂载、布局、事件、焦点,如下图:

View生命周期

问题九

打包流程

  • META-INF,存放签名信息,保证apk文件的完整性和系统安全
  • lib,如果存在的话,存NDK编译出来的so文件
  • res,存放anim、color、drawable、layout等资源文件,编译时会自动在R.java中生成索引文件
  • assets,存放原始资源文件,需要使用AssetManager来访问目录文件
  • resources.arsc,存放编译后的二进制资源文件
  • classes.dex,将编译生成的.class文件转换成dalvik字节码文件
  • AndroidManifest.xml,存放程序全局配置信息

问题十

  • Kotlin 定义变量,可以省略变量类型,JVM自动根据赋值情况确定类型
  • Kotlin 定义变量更加方便,用到valvar两个关键字
  • Kotlin 定义变量和函数更加方便,不需要指定变量、函数的作用域
  • Kotlin 定义函数统一使用关键字fun
  • Kotlin 定义的函数可以作为形参传递,也可以作为返回值传递
  • Kotlin 提供了更方便的运算符:可空类型(?)、安全调用运算符(?.)、安全转换运算符(as?)、null合并运算符(?:)和let运算符
  • Kotlin 创建类简化了代码量,继承类或实现接口统一使用冒号(:
  • Kotlin 定义接口,运行添加默认的实现
  • Kotlin 初始化对象,不再需要关键字new
  • Kotlin 类和方法默认都是final,不允许被继承,不允许被重写
  • Kotlin 使用open关键字定义一个类运行继承,使用open关键字定义一个方法运行被重写
  • Kotlin 接口不能使用关键字finalopenabstract,接口的成员始终都是open
  • Kotlin 省略修饰符,声明就是public
  • Kotlin 声明的内部类没有显示添加修饰符,默认为嵌套类;使用inner修饰符声明为内部类

问题十一

  • 广播,onReceive()方法中不适合做耗时的操作
  • Messenger,跨进程通信,实现Service跨进程更新UI界面
  • bindService,重写ServiceConnection接口方法,在服务连接或服务断开时做更新UI的操作
  • Service子类中传入Handler或Activity的引用,使用Handler发送消息到UI界面,在Handler的handleMessage()接收消息并更新UI

问题十二

  • 预加载本地图片转成Bitmap,使用LruCache进行缓存,设置将图片占据的内存大小并维持在一定范围内
  • 依次从LruCache读取需要展示的图片,内存不足的情况下会清除最近使用最少的Bitmap对象
  • 同时开启子线程在清除某个Bitmap对象的同时预加载另一个Bitmap对象存入LruCache
  • 循环执行:预加载——>展示——>清除——>预加载,保证展示动画的流畅性,同时防止OOM

附件:

Fragment生命周期

当前文章价值4.34元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://www.teachcourse.cn/2763.html ,谢谢支持!

资源分享

Android学习笔记九:Java线程、多线程和线程池 Android学习笔记九:Java线程、
Android电脑局域网操作手机的工具 Android电脑局域网操作手机的工
python编辑以发布wordpress文章 python编辑以发布wordpress文章
关于universal-image-loader如何防止Bitmap OOM的说明 关于universal-image-loader如何