Android 面试会问到的面试题(持续更新中)

Android知识点

1.Activity的启动过程(不要回答生命周期 )

  • 网址:http://www.cloudchou.com/android/post-788.html
  • 在Android系统中,有两种操作会引发Activity的启动,一种用户点击应用程序图标时,Launcher会为我们启动应用程序的主Activity;应用程序的默认Activity启动起来后,它又可以在内部通过调用startActvity接口启动新的Activity,依此类推,每一个Activity都可以在内部启动新的Activity。通过这种连锁反应,按需启动Activity,从而完成应用程序的功能。
  • Activity的启动方式有两种:显式和隐式,隐式启动可以使得Activity之间的耦合性更加松散

2.Activity的启动模式

  • standard和singleTop模式。这两种比较简单。创建Activity放入当前的任务栈中,若当前是singleInstace,则放入设置的任务栈中。其中如果Activity在栈顶,则调用onNewIntent。

  • singletask:栈内复用模式。不是在当前任务栈中查找是否存在,实际过程如下:

    查找该Activity所需的任务栈是否存在(由taskAffinity控制,或者默认为包名)。
    在任务栈当中查找该Activity是否存在。这里面存在任务栈的切换,也就是当开启的singtask类型的Activity不属于当前任务栈时,则会切换到其任务栈。

  • singleInstance:单实例模式。包含了singleTask的所有特性,另外加上:设置为该模式的Activity,只能单独存在于一个任务栈中。当有两个singleInstace的Activity设置成同样的任务栈时,会出现两个同名的任务栈,分别用来存放同名的Activity。注:在任何跳转的时候,首先调用本Activity的onPause,然后跳转。如果被跳转的activity由于启动方式而没创建新的实例,则会先调用onNewIntent,然后按照正常的生命周期调用。如1:A→B,A:onPause;B:onCreate,onStart,onResume。2:A(singleTop)→A,A:onPause;A:onSaveInstanceState;A:onResume。

3.Service的两种启动方式

Android 服务两种启动方式的区别 - 简书  https://www.jianshu.com/p/2fb6eb14fdec
  • 如果服务已开启,不会重复的执行onCreate()
  • (1)startService(),一旦服务开启就跟开启者没有关系了,开启者退出了,gauge了,服务也会在后台长期的运行,开启者不能调用服务里面的方法
  • (2)bindService() ,bind的方式开启服务,绑定服务,开启者挂了,服务也会跟着挂掉,并且绑定者可以使用服务里面的方法

4.Broadcast注册方式与区别

Android 两种注册、发送广播的区别 - 简书  https://www.jianshu.com/p/ea5e233d9f43
  • 动态注册:不是常驻型广播,也就是说广播跟随程序的生命周期
//new出上边定义好的BroadcastReceiver
MyBroadCastReceiver yBroadCastReceiver = new MyBroadCastReceiver();
//实例化过滤器并设置要过滤的广播  
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
//注册广播   
myContext.registerReceiver(smsBroadCastReceiver,intentFilter, 
             "android.permission.RECEIVE_SMS", null);
  • 静态注册:常驻型,也就是说当前应用程序关闭后,如果有信息广播来,程序也会系统调用自动运行
<receiver android:name=".MyBroadCastReceiver">  
            
            <intent-filter android:priority="20">
            <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>  
            intent-filter>  
receiver>

还要在同级的位置配置可能使用到的权限

<uses-permission android:name="android.permission.RECEIVE_SMS">
uses-permission>
  • 无需广播(sendBroiadcast):所有的接受者都会接受事件,不可以被拦截,不可以被修改
  • 有序广播(OrderedBroadcast):按照优先级,一级一级的向下传递,接受者可以修改广播数据,也可以终止广播事件
  • priority 优先级
  • 什么情况下需要动态注册:当一个程序退出之前,保证你的广播也跟着关闭,就要使用动态注册,如果用静态注册的话会在程序关闭后还仍保持着运行的状态,消耗内存,严重的话会造成OOM.

5.android开发中,可能会导致内存泄露的问题

  • 不要让生命周期长于Activity的对象持有到Activity的引用
  • 尽量使用Application的Context而不是Activity的Context
  • 尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用(具体可以查看细话Java:”失效”的private修饰符了解)。如果使用静态内部类,将外部实例引用作为弱引用持有。
  • 垃圾回收不能解决内存泄露,了解Android中垃圾回收机制**更多内容可以参考以下博客:http://spencer-dev.lofter.com/post/d7b9e_6faf120

6.Hybrid(重要加分项)

  • java和JS的交互http://droidyue.com/blog/2014/09/20/interaction-between-java-and-javascript-in-android/http://rensanning.iteye.com/blog/2043049
  • WebView开启JavaScript脚本执行
  • WebView设置供JavaScript调用的交互接口。

7.Activity切换时生命周期交集

  • Activity之间的协作当一个activity A启动了另外一个activityB,它们的生命周期是有交叉的;首先A的onPause()被调用;之后B的onCrate(), onStart()及onResume()
    方法会被调用(此时B拥有用户焦点);最后,如果A在屏幕上不可见,onStop()方法被调用;因此,我们在两个activities中传递数据,或者共享资源时(如数据库连接),需要在前一个activity的onPause()方法而不是onStop()方法中进行;

8.View的绘制

  • .推荐郭霖大神的博客:http://blog.csdn.net/guolin_blog/article/details/16330267
    View在Activity中显示出来,要经历测量、布局和绘制三个步骤,分别对应三个动作:measure、layout和draw。

1.测量:onMeasure()决定View的大小,;
2.布局:onLayout()决定View在ViewGroup中的位置;
3.绘制:onDraw()决定绘制这个View,分为6个步骤:(1)绘制视图的背景(2)保存画布的图层(3)绘制View的内容(4)绘制View子视图,如果没有就不用(5)还原图层(6)绘制滚动条。

自定义View的步骤:

  1. 自定义View的属性;

  2. 在View的构造方法中获得自定义的属性;

  3. 重写onMeasure(); –> 并不是必须的,大部分的时候还需要覆写

  4. 重写onDraw();

9.ActivityManagerService的相关知识点

  • 推荐以下博客:http://wiki.jikexueyuan.com/project/deep-android-v2/activity.html

10.canvas的使用

  • 推荐以下博客:http://blog.csdn.net/qinjuning/article/details/6936783

11.说一下是怎么快速定位并解决最近项目中遇到的问题

出现问题,肯定看错误日志,如果是本地调试出来的错误,可以直接看logcat,定位到报错代码的类,如果是一些简单的错误如:空指针异常,数组越界,io异常等等的话 一般是能够定位到报错的哪一行,根据逻辑进行调整就可以了;第一种情况很好解决问题,比较难搞的问题都是不会报出是哪一个类或者哪一行出现错误,而是直接报错,这时候就得根据报错的具体情况具体分析了,比如报出内存溢出的问题,一般都是在哪个地方去不停的去创建新的对象了,这时候就需要分析哪些地方做了重复的创建了。一般这个时候需要借助 debug调试或者打印log的方式进行错误排查。目前来说想到的就这两点,在现实中还有很多方式,比如单元测试进行部分逻辑的处理也是避免出现问题的方法

12.Android屏幕适配

屏幕适配就是使某一元素Android不同的尺寸、不同的分辨率上显示相同的效果

根据这个图,总结一下 :编写布局的时候,最好使用相对布局,它可以设置固定位置,灵活性强,查询显示的布局判断是否是单面板还是双面板,利用限定符进入单布局或者双布局,设置宽高属性最好使用wrap_content,match_parent,权重weight来设置,使用.9.png特殊处理过图片格式,可以自动拉伸,图片资源放到xxhdpi文件中,因为这个文件分辨率是1080X1920,符合大部分的手机设备,属性 大小使用dp和sp,谷歌出 了一个屏幕适配百分比框架,可根据情况依赖进行使用。

13.apk代码混淆

  • 推荐博客:https://blog.csdn.net/m0_37711172/article/details/79965973

注重说明以下:对代码进行混淆,就是为了防止被反编译,泄露代码机密,AS自身集成了Java中的ProGuard作为压缩,修改bulid.gradle中的minifyEnabled为true开启混淆,之后在moudle目录下照到proguard-rules.pro文件,现在混淆规则已经基本完善,从网上复制进去就可以了,混淆并不是把你的代码弄成乱码,而是把重要的代码避免被混淆

14.ViewPager和Fragment结合使用

当他们结合使用的时候,所需要的适配器并不是PagerAdapter,而是另外官方提供的FragmentPagerAdapter和FragmentStateAdapter,可以实现滑动效果,并且点击切换的时候也有,说明一下,一个是适用于显示fragment数量较少,另一个是显示fragment数量较多的时候使用。

15.ListView、GridView的优化

对于性能优化这方面,不管在任何时刻,都是比较常问的问题,先来说一下Listview:
1.在适配器getView()方法中尽量少写逻辑处理
2.不要再Viewholder类以外方法中创建对象,避免触发GC机制
3.在加载图片的时候,需要显示网络上加载的图片,那么要监听ListView滑动的时候,停止加载图片,滑动停止后再加载图片
4.将ListView的scrollingCache和animateCache设置为false,scrollingCache耗内存,默认开始,所以需要关闭掉,还有animateCache,会消耗大量的内存,会频繁调用GC,可以手动关闭掉
5.使用ViewHolder类
6.convertView的复用机制
7.使用分页加载功能,为了防止数据过多,出现OOM的异常
再来看一下GridView:
不说了,基本上是相同的,除了自带的属性

16.事件分发机制

  • 推荐博客:https://blog.csdn.net/m0_37711172/article/details/72818783#t9

1.Android 中的控件都是直接或者间接继承View的,Viewgroup也是继承View的,ViewGroup中可以包含View,也可以包含ViewGroup,我们平时接触的譬如说LinearLayout啊、RelativeLayout就是ViewGroup的子类。
2.Android中触摸事件的传递是先传递到ViewGroup,再传递View中,用Button举个列子来说明下大致流程
3.当点击Button的时候,会调用这个控件所在布局的dispatchTouchEvent(),然后在这个布局中dispatchTouchEvent()方法中找到被点击控件的dispatchTouchEvent()方法。
4.在调用被点击控件的dispatchTouchEvent()方法之前会有一次触摸事件的拦截判断,如果触摸事件被拦截了,就不会再去执行被点击控件的dispatchTouchEvent函数了,也就不会再执行onClick点击事件了。而是执行ViewGroup控件中的dispatchTouchEvent()的onTouch触摸事件然后返回。
5.如果触摸事件没被拦截的话又是怎么做呢,就会ViewGroup中dispatchTouchEvent()方法中被点击控件的dispatchTouchEvent()方法,就不会执行ViewGroup中的onTouch方法了。
6.以上只是阐述了touch事件在ViewGroup中和View中的事件分发过程,但是具体得在一个View中的touch事件分发机制又是怎么样的呢,我们继续往下看
7.android里面当触摸到任何一个控件的时候就一定会调用这个控件的dispatchTouchEvent方法。dispatchTouchEvent方法中的源码首先会调用onTouch方法,不过这个方法要执行的话也需要有两个前提条件,一个是这个控件注册了触摸监听、第二个是这个控件的状态要是enabled的。
8.执行完onTouch方法之后,会有一个返回值,如果返回这为true的话代表这个点击事件不继续往下传递了,为false的话就表示点击事件继续往下传递,就会执行onTouchEvent方法,onClick方法就是在onTouchEvent中被调用的。
9.这样的话一个控件的触摸事件在ViewGroup以及View中的分发过程就完成了。

17.自定义控件

推荐博客:https://blog.csdn.net/m0_37711172/article/details/79975225

18.动画

推荐博客:https://blog.csdn.net/m0_37711172/article/details/79924640
1.帧动画,AniimalDrawber,通过顺序的播放排列好的图片来实现
2.补件动画,可以使视图组件移动、放大、缩小以及产生透明度的变化,补件动画只能用在View上,只能实现移动、缩放、旋转和淡入淡出这四种动画操作
3.只是改变了View的显示效果而已,而不会真正去改变View的属性
3.属性动画,全新的动画模式,功能很强大,弥补了之前补件动画的位置不变的缺陷,完全可以取代补件动画,更改的时控件的属性

19.图片加载框架的优缺点

  1. imageloader ,最老的最火的图片加载库,使用的人挺多的,但是不维护了,不过还是用的人挺多的
  2. Picasso,代码简洁,api数量少
  3. Glide 完全基于Picasso,并进行大量的优化,默认格式RGB_565,内存是Picasso的的一半,在磁盘缓存方法,Picasso缓存的原始尺寸的图片,而Glide缓存的是多种规格,Glide会根据ImageView的大小来缓存相应大小的图片尺寸,Glide支持Gif动态图,而且还可以加载本地图片

20.Retrofit

21.MVC和MVP的区别?

就是一句话,如果代码逻辑写在View中,就是MVC,没有就是MVP,MVP模式逻辑都写再P中,而MVC中逻辑写在V中,比如当你点击Buttton的时候,button点击监听的时候,业务逻辑如果写再里面那就是MVC模式
1.MVP模式,View不直接和Model交互,而是通过与Presenter交互来与Model间接交互,Presenter与View的交互是通过接口来进行的更加有利于单元测试,通过VIew与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑
2.MVC模式,View可以与Model直接交互,Controoller是基于行为的,并且可以被多个View共享,可以负责决定哪个View

22.Okhttp的优缺点

1,支持http,https请求
2,支持文件下载
3,支持get,post请求
4,基于http的文件上传

1,封装麻烦
2,callback是在子线程里面,不能刷新ui,需要手动处理

你可能感兴趣的:(Android,我不是程序员)