Retrofit
1、retrofit(底层用okhttp做网络处理)使用
(1)添加依赖(在gradle中)
(2)创建用于网络请求的接口(使用注解描述网络请求参数)
(3)创建retrofit实例(设置网络请求url地址)
(4)发送请求(请求分为同步请求和异步请求)
2、retrofit添加扩展
(1)OkhttpClient(.client(mClient))
扩展Interceptor拦截器(addInterceptor(InterceptorUtil.LogInterceptor()))
(2)addConverterFactory(.addConverterFactory(GsonConverterFactory.create()))
对返回数据类型自动转换,可以自定义GsonConverterFactory,在其中可以对上传数据加密,返回数据解密
(3)addCallAdapterFactory(.addCallAdapterFactory(RxJava2CallAdapterFactory.create()))
把retrofit中执行的网络请求的Call对象转换为接口中定义的Call对象
3、retrofit实现原理(动态代理、方法注解、建造者,适配器)
(1)动态代理
ServiceMethod 存储我们传入网络请求的所有信息,为后面是适配转换提供转换目标
Retrofit内部默认使用OkhttpCall对象处理网络请求,返回的网络工作对象是经过适配器转换的
(2)建造者模式(.build())
创建OkHttpClient处理网络请求
设置默认的callAdapterFactory(Platform中为Android系统设定 ExecutorCallAdapterFactory)
(3)具体过程
首先根据NetService中定义的函数,解析函数,得到函数具体定义,并生成对应的ServiceMethod
然后根据这个ServiceMethod,实现一个OkHttpCall的Call对象,负责Retrofit底层实现网络请求
其中,在网络访问返回的网络数据时,根据ServiceMethod实现数据转换最后,利用上一节中匹配
的适配器,把OkhttpCall对象转换为NetService要求的Call网络请求对象
(4)网络请求
OkHttpCall继承的retrofit2.Call接口是为了依赖倒置解藕,真正的网络请求是有OkHttpCall内部引用的。
okhttp3.call处理的,这个okhttp3.call是借道ServoceMethod获取deRetrofit中的callFactory, 也就是retrofit
中的okhttpclient,最终的网络请求是由OkHttpCall调用的OkHttpClient发出的,调用和回调过程,也就是在
OkHttpCall处理
(5)数据转换
因为回调是在OkHttpCall中处理的,所以对回调数据的转换也在OkHttpCall中出发,为了符合接口函数中定义
的返回数据类型,OkHttpCall会调用ServiceMethod来转换Response返回数据对象
(引用:https://www.jianshu.com/p/f57b7cdb1c99)
4、优点
(1)可以将定义与使用分离开来
(2)支持多种返回数据解析的Conveter快速进行数据转换
(3)和Rxjava集成的很好
(4)继承OkHttp优秀性能,使用Okio来大大简化数据的访问与存储,增强java.io和java.nio
所以Retrofit性能比AsyncTask和Volley快
Volley
1、2.3以下是Httpclient。 2.3以上基于HttpUrlconnection
2、HttpClient存在的API数量过多,扩展困难
1、使用
(1)创建okhttpClient对象
OkhttpClient client = new OkhttpClient()
(2)创建Request
Request request = new Request.Builder()
.url(url)
.get()
.build();
(3)创建Call对象
Call call = client.newCall(request);
(4)通过 execute(),enqueue()方法获得请求响应Response对象
Response response = call.execute()
二、RxJava
1、观察者模式
(1)Observable(被观察者)
(2)Observer(观察者,订阅者)
2、异步和链式编程
(1)Scheduler(调度器)
observeOn(AndroidSchedulers.mainThread()) 事件回调线程
subscribeOn(Schedulers.io()) 事件执行的线程 Schedulers.io()子线程(可以重用空闲线程)
(2)切换线程
subscribeOn()指定被观察者的执行线程,对前面被观察者起作用创建一个新的Observable返回
下游,然后它重写call中,没有调用subscribe()而是直接调用了上游的call(),因为它除了切换线程之
外并没有其他事情需要做,对同一个Observable进行多次切换线程,起作用的只有第一个线程.(多
次执行线程切换,不论外面包多少层线程,都是在最内部线程执行的)ObservableSubscribeOn()设
置Disposable,最重要的就是scheduler.scheduleDirect(new SubscribeTask(parent)),这个方法首
先创建SubscribeTask,这个其实就是一个runable,在run方法里进行订阅操作
observeOn()指定观察者的执行线程
对后面的subscribe方法起作用,subscribe用了设置我们的观察者,也就是我们对于观察者发送的数据
的处理方法执行observeOn(),先将Observable封装成ObservableObserveOn ,创建Worker封装冲
ObserveOnObserver因为observeOn对后面的obsever起作用,所以最后subscribe执行的线程将会是最
外面线程
subscribe()
Rxjava订阅入口,直接返回disposable,最终subscribe调用subscribeActual,最终调用到Observble的
subscribleActual
1、get是从服务器上获取数据,post向服务器传送数据
2、get传送的数据量较小,不能大于2kb,post传送数据量较大,一般被默认不受限制
3、get安全性非常低,post安全性比较高,但执行效率却比post方法好
1、Glide
2、Picasso
3、fresco
1、网络缓存 从资源获取资源(异步加载) 网络缓存,不优先加载,速度慢,浪费流量
2、本地缓存 从本地获取数据(File存储) 本地缓存,次优先加载,速度快
3、内存缓存 从内存获取数据(LruCache) 内存缓存,优先加载,速度还
(1)线程的生命周期:
join()方法的作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻
塞,等待线程x销毁后再继续执行线程z后面的代码. join()内部调用wait(),所以join()具有释放锁的特点
(3)wait()(等待) sleep()(睡眠)
wait()来自Object ,释放了对象锁,使得其他线程可以使用同步控制块或方法sleep()来自Thread,没有释
放对象锁wait(),notify(),notifyAll()必须在synchronized执行
(4)yield()
礼让一下别的线程
(5)线程的终止
1、使用标志位来突出
2、使用interrupt()方法
分两种状态:阻塞状况和正常情况
阻塞情况:例如线程休眠时,使用interrupt()方法来抛出InterruptedException异常外,还会调用interrupted()
函数,调用时能获取中断状态时true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过
isInterrupt()获取不到中断状态时true,从而不能退出循环.
3、stop方法
强行终止,很危险,一般任何进行加锁的代码块,都是为了保护数据的一致性,stop()该线程所持有的锁的
突然释放,那么被保护数据就有可能呈现不一致性,其它线程可能 使用这些被破坏的数据
此方法实现多线程,这样耦合性更低,而且可以实现类的扩展性更好,因为java类支持实现多接口
(1)避免基础Thread类的单继承和局限性【类只能单继承,继承Thread类就不能继承其他类,而实现
Runnable接口就可以继承其他类和实现其他接口】
(2)降低类线程对象和线程任务的耦合性,增强了程序的扩展性【实现Runnable接口的方式,把设置线
程任务和开启新线程进行了分离(实现解耦)实现类中,重写了run方法来设置线程任务创建Thread类
对象,调用start方法来开启新线程创建Thread类对象,构造方法中传递Runnable接口的实现类对象,
可以传递不同的实现类(可扩展性)】
(3)实现Runnable接口将线程单独进行对象的封装,更符合面向对象思想。
(1)Message:消息,就是一个载体,包含消息ID,消息处理对象和消息等,统一放到MessageQueue,由Handler处理
(2)Handler:用于同一个进程放入线程间通信,消息处理
(3)MessageQueue插入和删除Message
(4)Looper轮询Message
(5)Handler发送消息调用MessageQueue的enqueueMessage向插入一条信息到MessageQueue,
Looper不断轮询调用MessageQueue的next方法,发现message就调用handler的dispatchMessage,
调用handlerMessage处理消息
(6)创建新的线程,真正卡死线程操作的是在回调方法onCreate,onStart,onResume等操作时间过长
会导致ANR,Looper.loop()本身不会导致应用卡死
(1)原理
AsyncTask的实现原理 = 线程池 + Handler
线程池用于线程调度、复用&执行任务;
Handler用于异步通信,将工作线程的执行结果传递给主线程
(2)核心方法
execute(params):触发异步任务,ui线程调用
onPreExecute()执行任务前自动调用,用于界面初始化
doInBackground(params)执行耗时操作,不能更改ui组件,调用publishProgress()更新进度
onProgressUpdate(progress):显示线程任务进度,调用publsihProgress(),自动调用
onPostExecute(result)执行结果显示到ui组件,执行结束自动调用
onCancelled():将异步设置取消状态,异步任务被取消时,自动调用
(3)多个运行方式
在1.6之前,AsyncTask是串行执行任务
1.6的时候,AsyncTask是并行执行任务
3.0开始时,AsyncTask是串行执行任务
1、特点
HandlerThread本质是一个线程类,它继承Thread;HandlerThread有自己的内部Looper对象,可以进行looper循环;
通过获取HandlerThread的looper对象传递给Handler对象,可以在handleMessage,方法中执行异步任务;
创建HandlerThread后必须先调用HandlerThread.start(),Thread会调用run方法,创建Looper对象.
2、使用步骤
HandlerThread handlerThread = new HandlerThread(“downloadImage”);
handlerThread.start();
class ChildCallback implements Handler.CallBack{
handleMessage(Message msg){
mUIHandler.sendMessage(msg1);
Return false;
}
}
Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());
1、 特点
本质是一种特殊的Service,继承自Service并且本身就是一个抽象类,可以在后台执行耗时异步任务,
任务完成自动停止,拥有较高优先级,适合执行较高优先级高的异步任务 内部通过HandlerThread和
Handler实现异步任务,创建只需要onHandleIntent和构造方法,onHandleIntent为异步,可以耗时
2、与Service区别
(1) Service中的程序运行中主程序中,IntentService中的程序运行在异步后台程序中
(2) Service中当我们后台服务执行完毕需要在外部组件中调用stopService()销毁服务,IntentService()
会在执行完毕后自动销毁
1、单例模式
(1)构造函数为private,不对外开发
(2)通过一个静态方法返回单例对象
(3)饿汉式,懒汉式
饿汉式:保证线程的安全性,由于类加载的时候会创建实例,会降低内存的使用率,
访问量大或访问线程多的时候,使用饿汉式
懒汉式:非线程安全,懒加载,第一次使用才会实例化单例对象, 访问量小的时候,
可以使用饿汉式
(4)单例模式的使用场景
需要频繁的进行创建和销毁的对象;
创建对象时耗时过多或浪费资源过多,但经常用到对象
工具类对象;
频繁访问数据库或文件的对象
1、使用
重写SQLiteOpenHelper——>建表(execSQL(sql))——>增删改查
2、事物(transaction())
使用(beginTransaction()、setTransactionSuccessful()、endTransaction())
作用:判断事务的标记是否成功,如果不成功,回滚错误之前执行的sql语句
3、升级
onUpgrate():通过数据库版本比较写SQL增加表字段、创建新表等操作来到达数据库升级功能
1、分类
(1)List、Set两个继承Collection接口,Map为独立接口
(2)Set下有HashSet、LinkedHashSet、TreeSet
(3)List下有ArrayList、Vector、LinkedList
(4)Map下有Hashtable、LinkedHashMap、HashMap、TreeMap
2、总结
(1)List有序,可重复
ArrayList :底层是数组,查询快,增删慢 线程不安全,效率高
Vector :底层是数组、查询快、增删慢 线程安全、效率低
LinkedList :底层是链表、查询慢、增删快 线程不安全、效率高
(2)Set无序,唯一
HashSet :底层哈希表,保证唯一性的两个方法(hashCode()和equals())
LinkedHashSet:底层是链表和哈希表、有序和元素唯一性
TreeSet :底层是红黑树、唯一、有序
(3)Map
TreeMap :实现sortMap,能够把保存的记录按照键排序(默认生序)
HashMap :非线程安全,最多只允许一条记录的键为null,允许许多记录值为null
(可以使用synchronziedMap或concurrentHashMap有同步能力)
HashTable :线程安全,不允许记录的键或值为空
LinkedHashMap:HashMap的子类,保持记录的插入顺序
1、dispatchTouchEvent() 事件分发方法
(1)该方法会将根元素的事件自上而下以此分发到内层元素,返回false则不拦截继续向下分发,
2、onInterceptTouchEvent() 事件拦截方法
(1)返回false不拦截事件,Touch事件就会向下传递给其子View返回true,事件被拦截,被当前ViewGroup处理,
调用该OnTouchEvent()方法
3、onTouchEvent() 事件响应方法
(1)返回true则表示该View能处理该事件,事件将终止向上传递返回false表示不能处理,则把事件传递
给onTouchEvent()
4、总结
(1)onTouchEvent()返回true来表示对该事件处理,返回false则没有成功处理事件,将会 将事件逐层向上传递,
交给上层View的onTouchEvent()方法处理,依次类推,直至某一 View成功处理事件,或者到顶层View处理仍
返回false则放弃对该事件处理,事件消失
5.onClick、onLongClick与onTouchEvent()
(1)同一个View同时覆写了三个方法,onTouchEvent最先捕捉到ACTION_DOWN和ACTION_UP事件,其次出
发onClick或者onLongClick
(2)onTouch ACTION_DOWN ->onTouch ACTION_UP -> onClick
(3)onTouch ACTION_DOWN ->onLongClick ->onTouch ACTION_UP
(4)onTouch ACTION_DOWN ->onLongClick ->onTouch ACTION_UP ->onClick
1、standard:activity默认的启动模式,每次启动一个activity都会实例化一个activity,新创建的activity会在堆栈中的栈顶
2、singleTop:如果当前要启动的activity在栈顶的位置,那么就会复用该activity,并且不会重走oncreate(),会直接走它的
onNewIntent(),如果不再栈顶和standard一样,例如:推送,如果当前的activity已在前台显示,突然来了一
条推送,此时不想让接收推送的消息的activity再次创建,那么此时正好可以用该启动模式,如果之前activity栈中
是 A-->B-->C如果点击了推动的消息还是A-->B--C,不过此时C是不会再次创建的,而是调用C的onNewIntent。而
如果现在activity中栈是A-->C-->B,再次打开推送的消息,此时跟正常的启动C就没啥区别了,当前栈中就是A--
>C-->B-->C了
3、singleTask:在activity堆栈中只要一个activity,例如:一般首页用到这种启动模式
4、singleInstance:activity永远在一个单独栈里,一旦activity实例化在栈中,任何激活该activity的行为都会重启该栈中的activity