扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
在工作中有不少朋友联系我,问我有没有相关推荐的书或者资料可以学习的。
自己也在不断的学习和提升,所以再这些过程中吧遇到的面试题整理了出来成都创新互联主营番禺网站建设的网络公司,主营网站建设方案,成都App制作,番禺h5微信小程序搭建,番禺网站营销推广欢迎番禺等地区企业咨询
(更多完整项目下载。未完待续。源码。图文知识后续上传github。)
可以点击关于我联系我获取完整PDF
(VX:mm14525201314)
onCreate()
-> onStart()
-> onResume()
-> onPause()
-> onStop()
-> onDetroy()
service 启动方式有两种,一种是通过startService()
方式进行启动,另一种是通过bindService()
方式进行启动。不同的启动方式他们的生命周期是不一样.
通过startService()
这种方式启动的service,生命周期是这样:调用startService()
--> onCreate()
--> onStartConmon()
--> onDestroy()
。这种方式启动的话,需要注意一下几个问题,
第一:当我们通过startService
被调用以后,多次在调用startService()
,onCreate()
方法也只会被调用一次,而onStartConmon()
会被多次调用当我们调用stopService()
的时候,onDestroy()
就会被调用,从而销毁服务。
第二:当我们通过startService
启动时候,通过intent传值,在onStartConmon()
方法中获取值的时候,一定要先判断intent是否为null。
通过bindService()
方式进行绑定,这种方式绑定service,生命周期走法:bindService
-->onCreate()
-->onBind()
-->unBind()
-->onDestroy()
bingservice
这种方式进行启动service好处是更加便利activity中操作service,比如加入service中有几个方法,a,b ,如果要在activity中调用,在需要在activity获取ServiceConnection
对象,通过ServiceConnection
来获取service中内部类的类对象,然后通过这个类对象就可以调用类中的方法,当然这个类需要继承Binder对象
app启动的过程有两种情况,第一种是从桌面launcher上点击相应的应用图标,第二种是在activity中通过调用startActivity
来启动一个新的activity。
我们创建一个新的项目,默认的根activity都是MainActivity
,而所有的activity都是保存在堆栈中的,我们启动一个新的activity就会放在上一个activity上面,而我们从桌面点击应用图标的时候,由于launcher本身也是一个应用,当我们点击图标的时候,系统就会调用startActivitySately()
,一般情况下,我们所启动的activity的相关信息都会保存在intent中,比如action,category等等。我们在安装这个应用的时候,系统也会启动一个PackaManagerService
的管理服务,这个管理服务会对AndroidManifest.xml
文件进行解析,从而得到应用程序中的相关信息,比如service,activity,Broadcast等等,然后获得相关组件的信息。
当我们点击应用图标的时候,就会调用startActivitySately()
方法,而这个方法内部则是调用startActivty()
,而startActivity()
方法最终还是会调用startActivityForResult()
这个方法。而在startActivityForResult()
这个方法。因为startActivityForResult()
方法是有返回结果的,所以系统就直接给一个-1,就表示不需要结果返回了。
而startActivityForResult()
这个方法实际是通过Instrumentation类中的execStartActivity()
方法来启动activity,Instrumentation这个类主要作用就是监控程序和系统之间的交互。而在这个execStartActivity()
方法中会获取ActivityManagerService
的代理对象,通过这个代理对象进行启动activity。启动会就会调用一个checkStartActivityResult()
方法,如果说没有在配置清单中配置有这个组件,就会在这个方法中抛出异常了。当然最后是调用的是Application.scheduleLaunchActivity()
进行启动activity,而这个方法中通过获取得到一个ActivityClientRecord
对象,而这个ActivityClientRecord
通过handler来进行消息的发送,系统内部会将每一个activity组件使用ActivityClientRecord
对象来进行描述,而ActivityClientRecord
对象中保存有一个LoaderApk
对象,通过这个对象调用handleLaunchActivity
来启动activity组件,而页面的生命周期方法也就是在这个方法中进行调用。
此处延伸:Volley里用的哪种请求方式(2.3前HttpClient
,2.3后HttpUrlConnection
)
首先HttpClient
和HttpUrlConnection
这两种方式都支持Https
协议,都是以流的形式进行上传或者下载数据,也可以说是以流的形式进行数据的传输,还有ipv6,以及连接池等功能。HttpClient这个拥有非常多的API,所以如果想要进行扩展的话,并且不破坏它的兼容性的话,很难进行扩展,也就是这个原因,Google在Android6.0的时候,直接就弃用了这个HttpClient.
而HttpUrlConnection
相对来说就是比较轻量级了,API比较少,容易扩展,并且能够满足Android大部分的数据传输。比较经典的一个框架volley,在2.3版本以前都是使用HttpClient
,在2.3以后就使用了HttpUrlConnection
。
Java虚拟机:
Dalvik虚拟机:
此处延伸:进程的优先级是什么
Context是一个抽象基类。在翻译为上下文,也可以理解为环境,是提供一些程序的运行环境基础信息。Context下有两个子类,ContextWrapper
是上下文功能的封装类,而ContextImpl
则是上下文功能的实现类。
而ContextWrapper
又有三个直接的子类, ContextThemeWrapper
、Service
和Application
。其中,ContextThemeWrapper
是一个带主题的封装类,而它有一个直接子类就是Activity,所以Activity和Service以及Application的Context是不一样的,只有Activity需要主题,Service不需要主题。Context一共有三种类型,分别是Application、Activity和Service。这三个类虽然分别各种承担着不同的作用,但它们都属于Context的一种,而它们具体Context的功能则是由ContextImpl
类去实现的,因此在绝大多数场景下,Activity、Service和Application这三种类型的Context都是可以通用的。不过有几种场景比较特殊,比如启动Activity,还有弹出Dialog。
出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个Activity的启动必须要建立在另一个Activity的基础之上,也就是以此形成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog),因此在这种场景下,我们只能使用Activity类型的Context,否则将会出错。
getApplicationContext()
和getApplication()
方法得到的对象都是同一个application对象,只是对象的类型不一样。
Context数量 = Activity数量 + Service数量 + 1 (1为Application)
这个问题真的很不好回答。所以这里先来个算是比较恰当的比喻来形容下它们的关系吧。Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图)LayoutInflater
像剪刀,Xml
配置像窗花图纸。
1Activity构造的时候会初始化一个Window,准确的说是
PhoneWindow
。
2这个PhoneWindow
有一个“ViewRoot
”,这个“ViewRoot
”是一个View或者说ViewGroup
,是最初始的根视图。
3“ViewRoot
”通过addView
方法来一个个的添加View。比如TextView
,Button
等
4这些View的事件监听,是由WindowManagerService
来接受消息,并且回调Activity函数。比如onClickListener
,onKeyDown
等。
此处延伸:栈(First In Last Out)与队列(First In First Out)的区别
栈与队列的区别:
1. 队列先进先出,栈先进后出
- 对插入和删除操作的"限定"。 栈是限定只能在表的一端进行插入和删除操作的线性表。 队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
- 遍历数据速度不同
standard 模式
这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。使用场景:大多数Activity。
singleTop 模式
如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent()
),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。使用场景如新闻类或者阅读类App的内容页面。
singleTask 模式
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent()
)。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。使用场景如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent
,并且会清空主界面上面的其他页面。
singleInstance 模式
在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent()
)。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。使用场景如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance
不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance
) -> C,完全退出后,在此启动,首先打开的是B。
帧动画:指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果,比如想听的律动条。
补间动画:指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。注意:只是在视图层实现了动画效果,并没有真正改变View的属性,比如滑动列表,改变标题栏的透明度。
属性动画:在Android3.0的时候才支持,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。比如view的旋转,放大,缩小。
此处延伸:简述Binder
AIDL: 每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。而aidl就类似与两个进程之间的桥梁,使得两个进程之间可以进行数据的传输,跨进程通信有多种选择,比如 BroadcastReceiver
, Messenger 等,但是 BroadcastReceiver
占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行。
Binde机制简单理解:
在Android系统的Binder机制中,是有Client
,Service
,ServiceManager
,Binder
驱动程序组成的,其中Client
,service
,Service Manager
运行在用户空间,Binder驱动程序是运行在内核空间的。而Binder就是把这4种组件粘合在一块的粘合剂,其中核心的组件就是Binder驱动程序,Service Manager
提供辅助管理的功能,而Client和Service正是在Binder驱动程序和Service Manager
提供的基础设施上实现C/S 之间的通信。其中Binder驱动程序提供设备文件/dev/binder与用户控件进行交互,
Client
、Service
,Service Manager
通过open和ioctl文件操作相应的方法与Binder驱动程序进行通信。而Client和Service之间的进程间通信是通过Binder驱动程序间接实现的。而Binder Manager是一个守护进程,用来管理Service,并向Client提供查询Service接口的能力。
Android中主线程是不能进行耗时操作的,子线程是不能进行更新UI的。所以就有了handler,它的作用就是实现线程之间的通信。
handler整个流程中,主要有四个对象,handler
,Message
,MessageQueue
,Looper
。当应用创建的时候,就会在主线程中创建handler对象,
我们通过要传送的消息保存到Message
中,handler通过调用sendMessage
方法将Message
发送到MessageQueue
中,Looper
对象就会不断的调用loop()方法
不断的从MessageQueue
中取出Message交给handler进行处理。从而实现线程之间的通信。
在Android系统的Binder机制中,是有Client
,Service
,ServiceManager
,Binder
驱动程序组成的,其中Client
,service
,Service Manager
运行在用户空间,Binder驱动程序是运行在内核空间的。而Binder就是把这4种组件粘合在一块的粘合剂,其中核心的组件就是Binder驱动程序,Service Manager
提供辅助管理的功能,而Client
和Service
正是在Binder驱动程序和Service Manager
提供的基础设施上实现C/S 之间的通信。其中Binder驱动程序提供设备文件/dev/binder与用户控件进行交互,Client
、Service
,Service Manager
通过open和ioctl文件操作相应的方法与Binder驱动程序进行通信。而Client和Service之间的进程间通信是通过Binder驱动程序间接实现的。而Binder Manager
是一个守护进程,用来管理Service,并向Client提供查询Service接口的能力。
我们知道Java虚拟机 —— JVM 是加载类的class文件的,而Android虚拟机——Dalvik/ART VM 是加载类的dex
文件,
而他们加载类的时候都需要ClassLoader,ClassLoader
有一个子类BaseDexClassLoader
,而BaseDexClassLoader
下有一个
数组——DexPathList
,是用来存放dex
文件,当BaseDexClassLoader
通过调用findClass
方法时,实际上就是遍历数组,
找到相应的dex
文件,找到,则直接将它return。而热修复的解决方法就是将新的dex
添加到该集合中,并且是在旧的dex
的前面,
所以就会优先被取出来并且return返回。
(1)对图片本身进行操作。尽量不要使用
setImageBitmap
、setImageResource
、BitmapFactory.decodeResource
来设置一张大图,因为这些方法在完成decode后,
最终都是通过java层的createBitmap
来完成的,需要消耗更多内存.
(2)图片进行缩放的比例,SDK中建议其值是2的指数值,值越大会导致图片不清晰。
(3)不用的图片记得调用图片的recycle()方法
此处延伸:手写mvp例子,与mvc之间的区别,mvp的优势
MVP模式,对应着Model--业务逻辑和实体模型,view--对应着activity,负责View的绘制以及与用户交互,Presenter--负责View和Model之间的交互,MVP模式是在MVC模式的基础上,将Model与View彻底分离使得项目的耦合性更低,在Mvc中项目中的activity对应着mvc中的C--Controllor
,而项目中的逻辑处理都是在这个C中处理,同时View与Model之间的交互,也是也就是说,mvc中所有的逻辑交互和用户交互,都是放在Controllor
中,也就是activity中。
View和model是可以直接通信的。而MVP模式则是分离的更加彻底,分工更加明确Model--业务逻辑和实体模型,view--负责与用户交互,Presenter 负责完成View于Model间的交互,MVP和MVC最大的区别是MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter
完成。还有一点就是Presenter
与View
之间的交互是通过接口的
(1)安装和下载Cygwin,下载 Android NDK
(2)在ndk项目中JNI接口的设计
(3)使用C/C++实现本地方法
(4)JNI生成动态链接库.so文件
(5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可
RecyclerView
可以完成ListView
,GridView
的效果,还可以完成瀑布流的效果。同时还可以设置列表的滚动方向(垂直或者水平);
RecyclerView
中view的复用不需要开发者自己写代码,系统已经帮封装完成了RecyclerView
可以进行局部刷新。
RecyclerView
提供了API来实现item的动画效果。
在性能上:
如果需要频繁的刷新数据,需要添加动画,则RecyclerView
有较大的优势。
如果只是作为列表展示,则两者区别并不是很大。
1、线程中sleep和wait的区别
2、Thread中的start()和run()方法有什么区别
3、关键字final和static是怎么使用的。
4、String,StringBuffer,StringBuilder区别
5、Java中重载和重写的区别:
6、Http https区别
7、Http位于TCP/IP模型中的第几层?为什么说Http是可靠的数据传输协议?
8、HTTP链接的特点
9、TCP和UDP的区别
10、Socket建立网络连接的步骤
11 、Tcp /IP 三次握手,四次挥 手
文章有点长,所以部分问题没有辅之答案,
所有的答案,请查看完整的PDF版
(更多完整项目下载。未完待续。源码。图文知识后续上传github。)
可以点击关于我联系我获取完整PDF
(VX:mm14525201314)
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流