对多线程的认识
创建线程的方法
继承Thread和实现Runnable。用Runnable接口创建的线程可以处理同一资源,而用Thread类创建的线程则各自独立处理,各自拥有自己的资源。
线程池。在执行大量异步任务时提高性能
AsyncTask。基于线程池和Handler的。调用execute()方法启动异步,
rxJava
// HandlerThread是集成了Looper和MessageQueue的线程,使用方法和普通线程一样
// IntentService是Service和HandlerThread的结合,使用HandlerThread来处理后台任务
线程池的分类
newCacheThreadPool
newFixThreadPool
newSingleTheadExecutor
newScheduleThreadPool
线程安全
使用原子类
synchronized。wait,notify,notityAll。wait与锁的机制配套实现,wait函数必须在有关键字synchronized修饰的同步块中使用。
Lock
volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。当变量被多个线程使用时,使用volatile修饰,这样可以保证变量可见。
线程同步
sleep。使一个正在运行的线程处于睡眠状态,
wait,notify,notityAll。使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁。唤醒一个处于等待状态的线程。唤醒所有处于等待状态的线程
线程间的通信方式
AsyncTask机制
Handler机制
rxJava
handler机制
handler通过sendMessage或post方法,将message插入到MessageQueue中。Looper循环地从MessageQueue中查询Message,如果时间到就从MessageQueue中取出Message并交给相应的handler处理。MessageQueue并非队列而是链表,插入Message时,会把时间较前的Message插入到前面位置。
Bitmap的处理
在加载图片时先进行边界压缩。新建Option,先读出图片的宽和高,再根据所需的宽和高来设置option的缩放比,再把图片加载出来。
在上传图片到服务器前对图片进行压缩,使用Bitmap的compress方法。
加载图片时可以使用BitmapFactory的decodeStream方法,因为使用其他方法加载图片都会用到createBitmap方法,这个方法会用到较多内存。
图片缓存处理,三级缓存。
对四个组件的认识
Activity 的四种启动模式
1、standard模式。每次启动activity时,都新建activity,并放入任务栈中。
2、singleTop模式。启动activity时,如果activity在任务栈顶,就调用activity的onNewIntent方法,如果不在栈顶,就新建activity并放入任务栈。
3、singleTask模式。启动activity时,如果activity在任务栈中,就把activity上的其他activity移出栈,同时调用activity的onNewIntent方法。如果activity不在任务栈中,就新建activity并放入任务栈。
4、singleInstance模式。启动activity时,会新建一个任务栈,将activity放入新的任务栈中。并保证新的任务栈只有一个activity。
Service的两种启动方式
startService 启动的服务:不能进行通信。service会一直无限期运行下去,使用stopService停止服务;
bindService 启动的服务:可以进行通信。使用unbindService停止服务,绑定到serivce上的组件可以是一个或多个(Activity),组件被销毁时,会解除与Service的绑定,也可以调用unbindService来解除绑定;
broadcaseReceiver用于系统或app发出的广播事件。broadcastReceiver注册方式有两种,在androidmainfest中注册称为静态注册,在代码里注册的动态注册。静态注册后,app可以一直接收广播,动态注册时当activity或service被销毁时就不能接收广播。
contentPrivoder是内容提供者,在android中如果想将自己的数据提供给别的应用,那么只能通过contentPrivoder来实现。contentPrivoder是应用程序间共享数据的接口。
Android内存泄露及管理
内存溢出 out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现OOM
内存泄露 memory leak:是指程序在申请内存后,无法释放已申请的内存空间
内存泄露
1、单例(主要原因还是因为一般情况下单例都是全局的,有时候会引用一些实际生命周期比较短的变量,导致其无法释放)
2、静态变量(同样也是因为生命周期比较长)
3、Handler内存泄露,非静态内部类会持有外部对象的引用。因为非静态内部类方法的调用需要依赖外部对象的创建。
4、匿名内部类(匿名内部类会引用外部类,导致无法释放,比如各种回调)
5、资源使用完未关闭(BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap)
6、线程,当线程没有执行完,就结束activity,会造成内存泄露
7、注册/反注册未成对使用(注册广播接受器、EventBus等,记得解绑。)
解决内存泄露
1、使用weakReference和solfReference。weakReference是当GC回收扫到这个对象时就会回收,solfReference在系统内存不足是会被回收。
2、handler使用时,在activity的onDestroy方法里清空messageQueue里的message和runnable。或者声名handler为静态内部类。
3、bitmap在读取图片时,可以先缩放再加载。在bitmap不使用时,recycle掉。
4、cursor和stream在等资源在使用完成时要关闭。
5、线程不再需要继续执行的时候要及时关闭。
6、将内部类、匿名内部类设置为静态。
7、记得反注册
检测内存泄露的工具:LeakCanary
APP优化
布局优化:尽量不要过于复杂的嵌套。可以使用<include>,<merge>,<ViewStub>
内存优化:参考内存泄露和内存溢出部分
图片优化:图片进行缩放的比例,不用的图片记得调用图片的recycle()方法
ANR
产生原因:
(1)5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).
(2)BroadcastReceiver在10s内无法结束
(3)Service 20s内无法结束(低概率)
解决方式:
(1)不要在主线程中做耗时的操作,而应放在子线程中来实现。如onCreate()和onResume()里尽可能少的去做创建操作。
(2)应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。
(3)避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
(4)service是运行在主线程的,所以在service中做耗时操作,必须要放在子线程中。
常用的设置模式
单例模式
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2、建造模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
3、代理模式
对用户进行权限管理,比如游客和登陆的用户都可以访问主界面,这时可以通过代理模式来分别对主界面进行操作。
4、观察者模式
一个对象发生改变时,所有依赖于它的对象自动做相应改变
5、工厂模式
定义一个用于创建对象的接口,让子类决定将哪一个类实例化。例如:BitmapFactory
如何做屏幕自适应
宽高限定符适配:穷举市面上所有的Android手机的宽高像素值
动态修改density值:修改density值使得设备有相同的dp值,一般把屏幕宽度设置成360dp。 https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA
网友评论