Activity生命周期:
onCreate: 创建活动,数据初始化操作。
onStart:可见-->不可见
onResume:与用户交互,位于栈顶
onPause:暂停,启动或恢复另一个活动时调用
onStop:停止,变为不可见
onDestroy:销毁
onRestart:停止->运行
Service生命周期
onCreate:首次创建服务,系统调用此方法。如果服务已在运行,则不会调用此方法,该方法只调用一次。
onStartCommand:另一个组件通过调用startService请求启动服务,系统调用此方法
onDestroy:服务不再使用被销毁,系统调用此方法。
onBind:另一个组件通过bindService与服务绑定时,系统调用此方法
onUnbind:另一个组件调用unBindService与服务解绑定,系统调用此方法。
onRebind:旧的组件与服务解绑后,另一个新组件与服务绑定,onUnbind返回true时,系统调用此方法。
Service启动方式
1、startService
定义一个类继承Service
在Manifest.xml文件配置该Service
使用context的startService(intent)启动该Service
不再使用时,调用stopService(intent)停止该服务
2、bindService
创建bindService服务,继承自Service并在类中实现binder接口的实例对象并提供公共方法给客户端调用
从onbind回掉方法返回此binder实例
在客户端中,从onServiceConnected回调方法接收binder,并使用提供的方法调用绑定服务
Activity启动方式
1、standard模式
activity默认启动模式
每启动一个activity在栈顶创建一个新的实例。例如:闹钟程序
缺点:每次创建新实例,不能直接复用
2、singleTop模式
判断要启动的activity是否位于栈顶,如果在则复用,否则新建实例。例如浏览器的书签
3、singleTask模式
Activity在整个应用程序只能中只有一个实例。每次启动activity时系统检测栈中是否存在当前Activity实例,存在则直接复用,并把当前Activity上所有实例全部出栈。例如:浏览器主界面
4、singleInstance模式
启动一个新的任务栈来管理Activity实例,在整个系统中只有一个。无论从哪个任务栈启动该activity,都会该activity所在任务栈移动到前台,从而使该activity显示。主要作用在不同程序中共享一个activity
Touch事件传递机制
点击屏幕时
Activity调用dispatchTouchEvent方法,事件传给Window;
Window再将事件传递给DecorView(DecorView是View根布局);
Decorview再传给ViewGroup;
Activity-->Window-->DecorView-->ViewGroup-->View
三个关键方法:
dispatchTouchEvent:分发
onInterceptTouchEvent:拦截,只有ViewGroup独有的方法
onTouchEvent:处理触摸事件
Activity首先调用dispatchTouchEvent进行分发,调用super向下传递
ViewGroup首先调用dispatchTouchEvent进行分发,接着调用onInterceptTouchEvent拦截。若拦截事件返回true,表示拦截,事件不会向下层的ViewGroup或者view传递;false,表示不拦截,继续分发事件。默认是false。View没有onInterceptTouchEvent方法的
事件在ViewGroup和ViewGroup、ViewGroup和View之间进行传递,最终到达View;
View调用dispatchTouchEvent方法,然后在onTouchEvent进行处理;onTouchEvent返回true,消耗事件,不再向下传递;返回false,表示不消耗事件,交回上层处理。
自定义View的基本流程
1、自定义View属性,编写attr.xml文件
2、在layout布局文件中引用,同时引用命名空间
3、在View的构造方法中获得我们自定义的属性,在自定义控件中进行读取(构造方法拿到attr.xml文件值)
4、重写onMesure
5、重写onDraw
Android中动画有哪些
逐帧动画(Frame Animation)
加载系列Drawable资源来创建动画,可以自定义每张图片的持续时间
补间动画(Tween Animation)
Tween可以对View实现一系列动画效果,比如:平移、缩放、旋转、透明等。但是并不会改变View的属性值,只改变view的绘制位置。比如:一个按钮动画过后,不在原来的位置显示,但是触发点击事件仍然在原来位置。
属性动画(Property Animation)
动画对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性被真实的改变了
ANR
Application Not Responding 无响应
三种原因:
1、KeyDispatchTimeout(5s)主要类型按键或触摸事件在特定时间内无响应
2、BroadcastTimeout(10s) BroadcastReceiver在特定的时间内无法处理
3、ServiceTimeout(20s)小概率类型Service在特定的时间内无法处理完成
避免在主线程减少耗时操作。
1、使用子线程处理耗时IO操作
2、降低子线程优先级,使用Thread或者HandlerThread时,调用Process.setThreadPriority(ProcessTHREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然降低程序响应,因为默认Thread优先级和主线程相同。
3、使用Handler处理子线程结果,而不是用Thread.wait或者Thread.sleep来阻塞主线程
4、activity的onCreate和onResume回掉中尽量避免耗时代码
5、BroadcastReceiver中onReceiver代码也要尽量减少耗时操作,建议使用intentService处理。intentService是一个异步的,会自动停止服务,很好解决传统的service中处理完耗时操作忘记停止销毁service的问题
设备横竖屏切换,页面周期变化
不设置activity的configchanges时,切屏会重新调用各个生命周期,切横屏执行一次,切竖屏执行两次。
设置configchanges=orientation时,切屏还是会调用生命周期,切横、竖屏只会执行一次。
设置configchanges=orientation|keyboardHidden时,切屏不会执行生命周期,只会执行onConfigurationChanged方法。
AndroidUI适配
字体使用sp,使用dp,match_parent,wrap_content,weight
图片资源,不同图片的分辨率,放响应文件夹百分比替代。
RecyclerView和ListView区别
RecyclerView可以完成ListView和GridView效果,瀑布流。可设置表滚动方向(垂直/水平)
RecyclerView的view复用不需要开发者写代码,系统已经封装好。可进行局部刷新。提供API来实现item动画效果。
性能上:
频繁刷新数据,需要添加动画,则RecyclerView较大优势。
只是展示列表,两者区别不大。
Android异步消息处理机制
解决子线程更新ui问题。
四部分:
1、Message(消息)
线程之间,内部携带少量消息,不同线程交换数据,可用what,arg1,arg2字段携带整型数据,obj携带Object对象
2、Handler(处理者)
发送和处理消息,sendMessage发送消息,handleMessage进行处理消息
3、MessageQueue(消息队列)
主要存放handler发送的消息,存在队列等待处理,每个线程只有一个MessageQueue
4、Looper(循环器)
调用loop方法后,不断从MessageQueue取出待处理的消息,然后传递给handleMessage进行处理
内存泄露和内存溢出
内存泄露(memory leak):在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,内存泄露堆积后果严重,迟早会耗光。
内存泄露:对象无法回收
内存泄露检测工具:LeakCanary
内存泄露原因:
1、Handler引起内存泄露
解决:将Handler声明为静态内部类,就不会持有外部类activity的引用。如果handler需要context,则通过弱引用引用外部类
2、单例引擎内存泄露
解决:Context用ApplicationContext(生命周期是整个app),不会导致内存泄露。
3、非静态内部类创建静态实例引起的内存泄露
解决:内部类修改为静态的就可以避免。
4、非静态匿名内部类引起内存泄露
解决:将匿名内部类设置为静态
5、注册/反注册未成对引起
注册广播接收器、EventBus等,记得解绑。
6、资源对象没有关闭引起内存泄露
类似close, destroy,recycler,release等释放
7、集合对象没有及时清理引起
一些对象装入集合中,不用后一定要清理,相关对象不再引用。
内存溢出(out of memory):程序在申请内存时,没有足够的内存空间使用;比如:申请一个integer,存long才能存下的数据,则内存溢出。内存不够用。
图片加载框架
ImageLoader:
优点:
支持下载进度监听
可以在View滚动中暂停图片加载
默认实现多种内存缓存算法。默认实现了较多缓存算法,如Size最大先删除,使用最少删除,最近最少使用,先进先删除,时间最长删除等
支持本地缓存文件命名规则定义。
缺点:
不支持GIF图片加载,缓存机制没有和http的缓存很好结合,完全自己一套缓存机制
Picasso:
优点:
统计监控功能,图片使用监控,缓存命中率、已使用内存大小、节省流量等
支持优先级处理
支持延迟到图片尺寸计算完成加载
支持飞行模式、并发线程数根据网络类型而变,手机切换到飞行模式或网络类型变换时会自动调整线程池最大并发数
无本地缓存。Picasso自己没有实现本地缓存,而由okhttp去实现,可以通过请求Response Header中的Cache-Control及Expired控制图片的过期时间。
缺点:
不支持GIF,默认使用ARGB_8888格式缓存图片,缓存体积大。
Glide:
优点:
1、图片缓存-->媒体缓存,支持Gif、WebP、缩略图。甚至是Video
2、支持优先级处理
3、与Activity/Frament生命周期一致,支持trimMemory
4、支持okhttp、Volley。Glide默认通过UrlConnection获取数据,可以配合okhttp或是Volley使用。实际ImageLoader、Picasso也都支持okhttp、Volley
5、内存友好,内存缓存更小图片,默认使用RGB565而不是ARGB888
缺点:
清晰度差,可以设置
Fresco:
优点:
1、匿名共享内存,而不是虚拟机的堆内存中,所以不会因为图片加载而导致oom,同时减少垃圾回收器频繁调用回收Bitmap导致的界面卡顿,性能高。
2、渐进式加载JPEG图片,支持图片从模糊到清晰加载
3、图片可以以任意中心点显示在ImageView,而不仅仅是图片中心
4、JPEG图片改变大小也是native进行的,不是虚拟机堆内存,同样减少OOM
5、很好的GIF图片显示
缺点:
框架大,影响apk体积,使用繁琐
网络架构
OkHttp
Android开发自带api是HttpClient,HttpUrlConnection进行操作。okhttp针对Java和Android程序,高性能http请求,支持同步、异步,okhttp封装线程池,数据转换,参数,错误处理等。但项目中需要自己封装,更顺手。
Retrofit
Retrofit是Square默认基于OkHttp封装一套RESTful网络请求框架,流行的api设计风格,不是标准。设计模式,通过注解直接配置请求,使用不同的http客户端,虽然默认是http,可以使用不同Json Converter来序列化数据,同时提供对Rxjava支持,使用Retrofit+OkHttp+RxJava+dagger2潮流框架,门槛高。
Volley:
Google官方小巧异步请求库,封装扩展性强,支持HttpClient、HttpUrlConnection,甚至支持Okhttp、而Volley里也封装了ImageLoader,甚至不需要图片加载框架,简单需求可以使用。Volley缺陷不支持post大数据,不适合上传文件。Volley设计初衷本身为频繁的、数据量小的网络请求。
Xutils:
可以网络请求,图片加载,数据存储,view进行注解。缺点,导致项目对框架依赖严重,框架出现问题,影响大。
Volley VS OkHttp
Volley优势在于封装更好,OkHttp需要足够的能力封装。OkHttp性能更高,OKHttp基于NIO和Okio,所以性能比Volley快。IO和NIO是Java概念,如果从磁盘读取数据,第一种方式程序一直等,数据读完后才能继续操作叫阻塞式IO,还有一种你读你的,程序接着往下执行,等数据处理完再通知,然后再处理回调,是NIO方式,非阻塞。所以NIO当然比IO性能好,而Okio是Square公司基于IO和NIO基础简单,高效处理库。理论上Volley和OkHttp对比,更倾向于使用Volley,因为Volley内部同样支持使用OkHttp,就没优势了,Volley本身封装也更容易,扩展性更好。
OkHttp VS Retrofit
Retrofit基于OkHttp做的封装,首选Retrofit