安卓面试题 基础篇
关于安卓面试题部分目前整理了两篇:
基础篇
进阶篇
安卓系统架构分层
安卓系统架构.jpg1)应用程序层
2)应用框架层
3)系统库和Android运行时
4)Linux内核
安卓四大组件是什么
Activity
Service
BroadcastReceiver
ContentProvider。
四大组件的生命周期和简单用法
https://www.jianshu.com/nb/21017066
Activity之间的通信方式
1.使用Intent传递数据,当传递引用类型时,对象是可序列化的。
2.类的静态变量
3.全局变量/Application
4.外部工具
5.SharedPreference
6.Android数据库SQLite
7.File
8.Android剪切板
9.Service
Activity各种情况下的生命周期
Activity的生命周期了解可以参考深入学习Activity
横竖屏切换的时候,Activity 各种情况下的生命周期
1.不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2.设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3.设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
Activity与Fragment之间生命周期比较
https://www.jianshu.com/p/0b1262be921b
两个Activity之间跳转时必然会执行的是哪几个方法?
当在A里面激活B组件的时候,A会调用onPause()方法,然后B调用onCreate() ,onStart(), onResume()。
这个时候B覆盖了A的窗体, A会调用onStop()方法。
如果B是个透明的窗口,或者是对话框的样式,就不会调用A的onStop()方法。
如果B已经存在于Activity栈中,B就不会调用onCreate()方法。
Activity的四种启动模式对比
1.standard 模式:
这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。
2.singleTop 模式:
如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。
3.singleTask 模式:
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
4.singleInstance 模式:
在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例(会调用实例的onNewIntent())。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。
Activity 怎么和Service 绑定?
使用bindService()函数。
Service和Activity怎么进行数据交互?
Activity通过bindService()成功实现与服务绑定后,利用Binder对象进行数据交互。
Service的生命周期与启动方法
startService():开启Service,调用者退出后Service仍然存在。
bindService():开启Service,调用者退出后Service也随即退出。
Service生命周期:
只是用startService()启动服务:onCreate() -> onStartCommand() -> onDestory
只是用bindService()绑定服务:onCreate() -> onBind() -> onUnBind() -> onDestory
同时使用startService()启动服务与bindService()绑定服务:onCreate() -> onStartCommnad() -> onBind() -> onUnBind() -> onDestory
谈谈你对ContentProvider的理解
ContentProvider一般为存储和获取数据提供统一的接口,可以在不同的应用程序之间共享数据。
说说ContentProvider、ContentResolver、ContentObserver 之间的关系
ContentProvider——内容提供者, 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider 对你应用中的数据进行添删改查。
ContentResolver——内容解析者, 其作用是按照一定规则访问内容提供者的数据(其实就是调用内容提供者自定义的接口来操作它的数据)。
ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。
广播的分类
有序广播
有序广播是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。此时的广播接收器是有先后顺序,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。
无序广播
无序广播是一种完全异步执行的广播,在广播发出去之后,所有的广播接收器几乎同时接收到这条广播消息,它们之间没有任何项目顺序可言。这种广播的效率比较高,但也意味着它是无法被截断的
广播使用的方式和场景
BroadcastReceiver的使用场景:
App全局监听:这种主要用于在AndroidManifest中静态注册的广播接收器,一般我们在收到该消息后,需要做一些相应的动作,而这些动作与当前App的组件,比如Activity或者Service的是否运行无关,比如我们在集成第三方Push SDK时,一般都会添加一个静态注册的BroadcastReceiver来监听Push消息,当有Push消息过来时,会在后台做一些网络请求或者发送通知等等。
组件局部监听:这种主要是在Activity或者Service中使用registerReceiver()动态注册的广播接收器,因为当我们收到一些特定的消息,比如网络连接发生变化时,我们可能需要在当前Activity页面给用户一些UI上的提示,或者将Service中的网络请求任务暂停。所以这种动态注册的广播接收器适合特定组件的特定消息处理。
在Manifest和代码中如何注册和使用BroadcastReceiver?本地广播和全局广播有什么差别?
动态注册的广播会受Activity的生命周期的影响,当Activity销毁的时候,广播就失效了。
静态注册的广播,即使Activity销毁了,仍然可以收到广播。
AlertDialog,PopupWindow相同与区别
1)AlertDialog是非阻塞式对话框:AlertDialog弹出时,后台还可以做事情;而PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一直等待,只有当我们调用了dismiss方法的后,PopupWindow退出,程序才会向下执行。
2) Popupwindow在显示之前一定要设置宽高,Dialog无此限制。
3) Popupwindow默认不会响应物理键盘的back,除非显示设置了popup.setFocusable(true);而在点击back的时候,Dialog会消失。
4) Popupwindow不会给页面其他的部分添加蒙层,而Dialog会。
5) Popupwindow没有标题,Dialog默认有标题,可以通过dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);取消标题
6) 二者显示的时候都要设置Gravity。如果不设置,Dialog默认是Gravity.CENTER。
7) 二者都有默认的背景,都可以通过
setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));
去掉。
Application和Activity的Context对象的区别
this.getApplicationContext()取的是这个应用程序的Context,Activity.this取的是这个Activity的Context。这两者的生命周期是不同的,前者的生命周期是整个应用,后者的生命周期只是它所在的Activity。
Android属性动画特性
属性动画改变的是对象的实际属性,不仅可以应用于View,有getter和setter方法的都可以。
如何导入外部数据库?
1.将格式为.db的数据库文件放到android项目assets目录中;
2.在程序必要的时候,将其“拷贝”(文件读取)到Android 程序默认的数据库存储目录中,一般路径为“/data/data/项目包名/databases/“;
3.自定义SQLiteOpenHelper类,创建一个名字跟步骤1中.db名称一样的数据库;
4.按照平常逻辑,增删改查数据库。
谈谈对接口与回调的理解
接口回调是指:可以把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口的方法。实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法。
回调的原理
接口调用自己的抽象方法,相当于接口的实现类调用实现类中重写的抽象方法;
介绍下SurfaceView
http://blog.csdn.net/android_cmos/article/details/68955134
Android里的Intent传递的数据有大小限制吗,如何解决?
Intent传递数据大小的限制大概在1M左右,超过这个限制就会静默崩溃。处理方式如下:
进程内:EventBus,文件缓存、磁盘缓存。
进程间:通过ContentProvider进行款进程数据共享和传递。
插值器与估值器
插值器用于设置属性值从初始值过渡到结束值的变化规律。
估值器用于设置属性值从初始值过渡到结束值的变化具体数值。
Android中数据存储方式
1.使用SharedPreferences存储数据
2.文件存储数据
3.SQLite数据库存储数据
4.使用ContentProvider存储数据
5.网络存储数据
Android动画框架实现原理
http://blog.csdn.net/harrain/article/details/53726960
requestLayout()、invalidate()与postInvalidate()有什么区别?
requestLayout():该方法会递归调用父窗口的requestLayout()方法,直到触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为true,会触发onMesaure()与onLayout()方法,不一定 会触发onDraw()方法。
invalidate():该方法递归调用父View的invalidateChildInParent()方法,直到调用ViewRootImpl的invalidateChildInParent()方法,最终触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为false,不会 触发onMesaure()与onLayout()方法,当时会触发onDraw()方法。
postInvalidate():该方法功能和invalidate()一样,只是它可以在非UI线程中调用。
一般说来需要重新布局就调用requestLayout()方法,需要重新绘制就调用invalidate()方法。
Activity-Window-View三者的差别
Activity负责创建一个Window用于显示View。Activity不能处理View对于View的处理交给Window负责。
如何优化自定义View
1)降低刷新频率
2)使用硬件加速
3)初始化时创建对象,不要在onDraw中创建
4)绘制状态的保存与恢复
描述一次网络请求的流程
浏览器地址框输入了域名并回车,然后通过DNS解析找到相应的IP地址;然后通过HTTP协议建立了链接,找到了目标服务器的位置;接着就是TCP三次握手建立可靠链接,发送数据,服务器处理数据,TCP四次挥手断开链接;最后浏览器根据返回的数据解析渲染呈现页面。