Fork me on GitHub
Wakaka

路漫漫其修远兮,吾将上下而求索


  • 首页

  • 关于

  • 标签

  • 归档

设计模式(1)

发表于 2018-07-04

设计模式的六大原则

名称 作用
开闭原则 对扩展开放,对修改关闭
里氏代换原则 任何基类可以出现的地方,子类一定可以出现
依赖倒转原则 针对接口编程,依赖于抽象而不依赖于具体
接口隔离原则 使用多个隔离的接口,比使用单个接口要好
迪米特法则 一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立
合成复用原则 尽量使用合成/聚合的方式,而不是使用继承

设计模式概述

序号 描述 具体
1 创造型模式:提供一种在创建对象的同时隐藏创建逻辑的方式,而不是使用new运算符直接实例化对象。 工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式
2 结构型模式:关注类和对象的组合。 适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式享元模式、代理模式
3 行为型模式:关注对象间的通信 责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、空对象模式、策略模式、模板模式、访问者模式

Android开发艺术探索---读书笔记(1)

发表于 2018-07-01

Activity

Activity:一种可以包含用户界面的组件,主要用于和用户进行交互。

Activity的生命周期

典型情况下的生命周期

什么是典型情况下的生命周期?
有用户参与情况下,Activity所经过的生命周期的改变。

阅读全文 »

OkHttp3(3)

发表于 2018-06-29

介绍

主要讲解OkHttp中的拦截器

拦截器流程

拦截器介绍

  • 负责失败重试以及重定向retryAndFollowUpInterceptor(请看这儿)
  • 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的BridgeInterceptor(请看这儿)
  • 负责读取缓存直接返回、更新缓存CacheInterceptor(请看这儿)
  • 负责和服务器建立连接ConnectInterceptor(请看这儿)
  • 负责向服务器发送请求数据、从服务器读取响应数据CallServerInterceptor(请看这儿)

retryAndFollowUpInterceptor流程图

BridgeInterceptor流程图

CacheInterceptor流程图

ConnectInterceptor流程图

CallServerInterceptor流程图

来源见跳转链接,侵删

OkHttp3(2)

发表于 2018-06-28

举个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String url = "https://raw.github.com/square/okhttp/master/README.md";
OkHttpClient okHttpClient = new OkHttpClient();

Request request = new Request.Builder().url(url).build();
okhttp3.Response response = null;
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: ");
}

@Override
public void onResponse(Call call, Response response) throws IOException {
String json = response.body().string();
Log.i(TAG,json);
}
});

源码分析

new OkHttpClient()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public OkHttpClient() {
//自动builder()
this(new Builder());
}

OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;

boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}

if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = systemDefaultTrustManager();
this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}

...

if (interceptors.contains(null)) {
throw new IllegalStateException("Null interceptor: " + interceptors);
}
if (networkInterceptors.contains(null)) {
throw new IllegalStateException("Null network interceptor: " + networkInterceptors);
}
}

new Request.Builder().url(url).build()

Builder()

1
2
3
4
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}

url()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");

// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}

HttpUrl parsed = HttpUrl.parse(url);
if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}

build()

1
2
3
4
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}

Request()

1
2
3
4
5
6
7
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}

发起HTTP请求

okHttpClient.newCall(request)

1
2
3
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}

根据请求创建新的Call,主要起作用的是newRealCall()

同步请求execute()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
  • 首先判断call是否执行过if (executed),每个call只能执行一次,如果还想要一样的call,可以通过clone()
1
2
3
4
@SuppressWarnings("CloneDoesntCallSuperClone") // We are a final type & this saves clearing state.
@Override public RealCall clone() {
return RealCall.newRealCall(client, originalRequest, forWebSocket);
}
  • client.dispatcher().executed(this);

执行call,HTTP请求的执行策略

  • getResponseWithInterceptorChain();

进行拦截操作,然后获得HTTP的返回结果

getResponseWithInterceptorChain源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));

Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());

return chain.proceed(originalRequest);
}
  1. 设置拦截器集合List<Interceptor> interceptors = new ArrayList<>();
  2. 将配置client时候的拦截器加入集合interceptors.addAll(client.interceptors());
  3. 负责失败重试以及重定向interceptors.add(retryAndFollowUpInterceptor);
  4. 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的interceptors.add(new BridgeInterceptor(client.cookieJar()));
  5. 负责读取缓存直接返回、更新缓存interceptors.add(new CacheInterceptor(client.internalCache()));
  6. 负责和服务器建立连接interceptors.add(new ConnectInterceptor(client));
  7. 配置OkHttpClient时设置的interceptors.addAll(client.networkInterceptors());
  8. 负责向服务器发送请求数据、从服务器读取响应数据interceptors.add(new CallServerInterceptor(forWebSocket));
  • client.dispatcher().finished(this);

通知dispatcher执行完毕

异步请求enqueue()

1
2
3
4
5
6
7
8
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
  runningAsyncCalls.add(call);
  executorService().execute(call);
} else {
  readyAsyncCalls.add(call);
}

}
…
}
```

dispatcher在当前执行的时候如果还可以执行一个并发请求,那就立刻执行,否则加入runningAsyncCalls队列,等待当前请求执行完成,然后再执行。

其他的和同步请求一样。

获取返回数据

在发起网络请求之后,我们就可以在Response中获取到返回的数据,包括状态码、状态信息、返回头、responsebody,返回的responsebody可能会非常大,所以必须要用通过数据流的方式进行访问,其他部分可以随意获取。

responsebody需要注意:

  1. 每个body只能被消费一次,多次消费会报异常
  2. body必须被关闭,不然会发生泄漏

HTTP缓存

之前的拦截器中,提到了负责缓存拦截器,所以在建立连接之前,我们应该检查相应是否被缓存、缓存是否可以用,如果是就直接返回缓存的数据,否则进行后面的步骤将返回的网络数据写进缓存。

缓存的具体缓存逻辑是在OkHttp中内置封装类一个Cache类,利用DiskLruCache,按照LRU算法进行缓存淘汰。

总结

图源见水印

OkHttp3(1)

发表于 2018-06-28

简介

翻译自官网

套话….

  • 支持http2,对一台机器的所有请求共享同一个socket
  • 内置连接池,支持连接复用,减少延迟
  • 支持透明的gzip压缩响应体
  • 通过缓存避免重复的请求
  • 请求失败时自动重试主机的其他备用ip,自动重定向
  • 好用的API
阅读全文 »

Retrofit2(1)

发表于 2018-06-28

用途

Retrofit is the class through which your API interfaces are turned into callable objects.

译:Retrofit通过设置的API接口转换为可以被调用的类。

所以,这样我们就可以知道Retrofit是一个HTTP框架,那么在没有Retrofit之前,我们是如何请求的。

阅读全文 »

RxJava2(5)

发表于 2018-06-27

三个方面分析RxJava2的实现:

  1. RxJava2基本流程的分析
  2. 操作符原理的分析
  3. 线程调度的分析

源码基于RxJava2(2.1.15版本)

RxJava2基本流程的分析

举个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("hello world!");
emitter.onComplete();
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, "onSubscribe: ");
}

@Override
public void onNext(String s) {
Log.i(TAG, "onNext: " + s);
}

@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: ");
}

@Override
public void onComplete() {
Log.i(TAG, "onComplete: ");
}
});
阅读全文 »

RxJava2(4)

发表于 2018-06-26

过滤操作符

filter()

作用

按照一定的逻辑筛选被观察者发送的事件

使用

1
2
3
4
5
6
7
8
9
10
11
12
    Observable.just(1,2,3,4,5,6)
.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer > 3;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: " + integer);
}
});

输出结果

1
2
3
06-26 10:50:00.860 21641-21641/com.example.bibingwei.androiddemo I/------: accept: 4
accept: 5
accept: 6
阅读全文 »

RxJava2(3)

发表于 2018-06-26

组合操作符

merge()

作用

将两个或多个观察者组合在一起,并行发送事件

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Observable.merge(Observable.interval(100,TimeUnit.MILLISECONDS).map(new Function<Long, String>() {
@Override
public String apply(Long aLong) {
return "A" + aLong;
}
}),Observable.interval(100,TimeUnit.MILLISECONDS).map(new Function<Long, String>() {
@Override
public String apply(Long aLong) {
return "B" + aLong;
}
})).subscribe(new Consumer<String>() {
@Override
public void accept(String s) {
Log.i(TAG, "accept: " + s);
}
});

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
accept: A0
accept: B0
accept: A1
accept: B1
accept: A2
accept: B2
accept: A3
accept: B3
...
accept: A13
accept: B13
accept: B14
accept: A14
accept: A15
accept: B15
accept: A16
accept: B16
//不保证顺序
阅读全文 »

RxJava2(2)

发表于 2018-06-25

变换操作符

map

作用

将观察者发送的数据类型转变为其他的数据类型

使用

1
2
3
4
5
6
7
8
9
10
11
12
Observable.just(1,2,3)
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer){
return "string: " + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s){
Log.i(TAG, "accept: " + "string: " + s);
}
});

输出结果

1
2
3
accept: string: 1
accept: string: 2
accept: string: 3
阅读全文 »
1…345…9

Wakaka

84 日志
25 标签

© 2018 Wakaka
本站访客数:
本站总访问量次 |
由 Hexo 强力驱动
|
主题 — NexT.Mist v5.1.3