Android中所涉及的常用設計模式
1、單例模式
概念:Ensure a class has only one instance, and provide a global point of access to it.
動態確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。
優點:
1.1、由于單例模式在內存中只有一個實例,減少了內存開銷。對于那些耗內存的類,只實例化一次,大大提高性能,尤其是移動開發中。
1.2、單例模式可以避免對資源的多重占用,例如一個寫文件時,由于只有一個實例存在內存中,避免對同一個資源文件的同時寫操作。
1.3、單例模式可以在系統設置全局的訪問點,優化和共享資源訪問。
public class Singleton {
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}</code></pre>
構造函數私有化,定 義靜態函數獲
得實例就不多說了,這里著重說一下volatile:
volatile本質是在告訴jvm當前變量在寄存器中的值是不確定的,需要從內存中讀取,synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住.(首先我們要先意識到有這樣的現象,編譯器為了加快程序運行的速度,對一些變量的寫操作會先在寄存器或者是CPU緩存上進行,最后才寫入內存.
而在這個過程,變量的新值對其他線程是不可見的.而volatile的作用就是使它修飾的變量的讀寫操作都必須在內存中進行!)
synchronized
同步塊大家都比較熟悉,通過 synchronized 關鍵字來實現,所有加上synchronized 和 塊語句,在多線程訪問的時候,同一時刻只能有一個線程能夠用
synchronized 修飾的方法 或者 代碼塊。
volatile
用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量修改后的最的值。volatile很容易被誤用,用來進行原子性操作。
再就是這個雙重判斷null :
這是因為如果線程A進入了該代碼,線程B 在等待,這是A線程創建完一個實例出來后,線程B 獲得鎖進入同步代碼,實例已經存在,木有必要再創建一個,所以雙重判斷有必要。
Android中 用到的地方很多,比如Android-Universal-Image-Loader中的單例,EventBus中的單例
最后給出一個管理我們activity的類,可以作為一個簡單工具類
public class ActivityManager {
private static volatile ActivityManager instance;
private Stack<Activity> mActivityStack = new Stack<Activity>();
private ActivityManager(){
}
public static ActivityManager getInstance(){
if (instance == null) {
synchronized (ActivityManager.class) {
if (instance == null) {
instance = new ActivityManager();
}
}
return instance;
}
public void addActicity(Activity act){
mActivityStack.push(act);
}
public void removeActivity(Activity act){
mActivityStack.remove(act);
}
public void killMyProcess(){
int nCount = mActivityStack.size();
for (int i = nCount - 1; i >= 0; i--) {
Activity activity = mActivityStack.get(i);
activity.finish();
}
mActivityStack.clear();
android.os.Process.killProcess(android.os.Process.myPid());
}
}</code></pre>
單例模式在Android源碼中的應用:
在Android源碼中,使用到單例模式的例子很多,如:
InputMethodManager類
public final class InputMethodManager {
static final boolean DEBUG = false;
static final String TAG = "InputMethodManager";
static final Object mInstanceSync = new Object();
static InputMethodManager mInstance;
final IInputMethodManager mService;
final Looper mMainLooper;</code></pre>
創建唯一的實例static InputMethodManager mInstance;
/**
* Retrieve the global InputMethodManager instance, creating it if it
* doesn't already exist.
* @hide
*/
static public InputMethodManager getInstance(Context context) {
return getInstance(context.getMainLooper());
}
/**
* Internally, the input method manager can't be context-dependent, so
* we have this here for the places that need it.
* @hide
*/
static public InputMethodManager getInstance(Looper mainLooper) {
synchronized (mInstanceSync) {
if (mInstance != null) {
return mInstance;
}
IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
mInstance = new InputMethodManager(service, mainLooper);
}
return mInstance;
}
防止多線程同時創建實例:
synchronized (mInstanceSync) {
if (mInstance != null ) {
return mInstance;
}
當沒有創建實例對象時,調用mInstance = new InputMethodManager(service, mainLooper);
其中類構造函數如下所示:
InputMethodManager(IInputMethodManager service, Looper looper) {
mService = service;
mMainLooper = looper;
mH = new H(looper);
mIInputContext = new ControlledInputConnectionWrapper(looper,
mDummyInputConnection);
if (mInstance == null) {
mInstance = this;
}
}
2、 建造者模式( Builder 模式 )
定義:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
概念就是比較抽象的,讓大家很難理解的,如果簡單從這個一個概念就搞懂了這個模式的話,那就不用費力的去查資料整理后邊的東西了。
這里我們通過一個例子來引出Build模式。假設有一個Person類,他的一些屬性可以為null,可以通過這個類來構架一大批人
public class Person {
private String name;
private int age;
private double height;
private double weight;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
然后為了方便,你可能會寫這么一個構造函數來傳屬性
public Person(String name, int age, double height, double weight) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}
或者為了更方便還會寫一個空的構造函數
public Person() {
}
有時候還會比較懶,只傳入某些參數,又會來寫這些構造函數
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
于是就可以來創建各種需要的類
Person p1=new Person();
Person p2=new Person("張三");
Person p3=new Person("李四",18);
Person p4=new Person("王二",21,180);
Person p5=new Person("麻子",16,170,65.4);
其實這種寫法的壞處在你寫的過程中想摔鍵盤的時候就該想到了,既然就是一個創建對象的過程,怎么這么繁瑣,并且構造函數參數過多,其他人創建對象的時候怎么知道各個參數代表什么意思呢,這個時候我們為了代碼的可讀性,就可以用一下Builder模式了
給Person類添加一個靜態Builder類,然后修改Person的構造函數,如下:
public class Person {
private String name;
private int age;
private double height;
private double weight;
privatePerson(Builder builder) {
this.name=builder.name;
this.age=builder.age;
this.height=builder.height;
this.weight=builder.weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
static class Builder{
private String name;
private int age;
private double height;
private double weight;
public Builder name(String name){
this.name=name;
return this;
}
public Builder age(int age){
this.age=age;
return this;
}
public Builder height(double height){
this.height=height;
return this;
}
public Builder weight(double weight){
this.weight=weight;
return this;
}
public Person build(){
return new Person(this);
}
}
}
從上邊代碼我們可以看到我們在Builder類中定義了一份跟Person類一樣的屬性,通過一系列的成員函數進行賦值,但是返回的都是this,最后提供了一個build函數來創建person對象,對應的在Person的構造函數中,傳入了 Builder
對象,然后依次對自己的成員變量進行賦值。此外,Builder的成員函數返回的都是this的另一個作用就是讓他支持鏈式調用,使代碼可讀性大大增強
于是我們就可以這樣創建Person對象
Person.Builder builder=new Person.Builder();
Person person=builder
.name("張三")
.age(18)
.height(178.5)
.weight(67.4)
.build();
是不是有那么點感覺了呢
Android中大量地方運用到了Builder模式,比如常見的對話框創建
AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("對話框")
.setIcon(android.R.drawable.ic_dialog)
.setView(R.layout.custom_view)
.setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
dialog.show();
其實在java中StringBuilder 和StringBuffer都用到了Builder模式,只不過是稍微簡單一點了
Gson中的GsonBuilder
GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
.disableHtmlEscaping()
.generateNonExecutableJson()
.serializeNulls()
.create();
網絡框架OKHttp
Request.Builder builder=new Request.Builder();
Request request=builder.addHeader("","")
.url("")
.post(body)
.build();
可見大量框架運用了Builder 設計模式,總結一下吧:
定義一個靜態內部類Builder,內部成員變量跟外部一樣
Builder通過一系列方法給成員變量賦值,并返回當前對象(this)
Builder類內部提供一個build方法方法或者create方法用于創建對應的外部類,該方法內部調用了外部類的一個私有化構造方法,該構造方法的參數就是內部類Builder
外部類提供一個私有化的構造方法供內部類調用,在該構造函數中完成成員變量的賦值
3、 觀察者模式
定義:Define a one-to-many dependency between objects so that when one object changes state, all its dependents aer notified and updated automatically.
定義對象間一種一對多的依賴關系,使得當一個對象改變狀態,則所有依賴于它的對象都會得到通知并被自動更新。
主要包括四個部分:
1. Subject被觀察者。是一個接口或者是抽象類,定義被觀察者必須實現的職責,它必須能偶動態地增加、取消觀察者,管理觀察者并通知觀察者。
2. Observer觀察者。觀察者接收到消息后,即進行update更新操作,對接收到的信息進行處理。
3. ConcreteSubject具體的被觀察者。定義被觀察者自己的業務邏輯,同時定義對哪些事件進行通知。
4. ConcreteObserver具體觀察者。每個觀察者在接收到信息后處理的方式不同,各個觀察者有自己的處理邏輯。
這個好像還好理解那么一點點,不過還是先來講個情景,
天氣預報的短信服務,一旦付費訂閱,每次天氣更新都會向你及時發送
其實就是我們無需每時每刻關注我們感興趣的東西,我們只需要訂閱它即可,一旦我們訂閱的事務有變化了,被訂閱的事務就會即時的通知我們
我們來看一下觀察者模式的組成:
- 觀察者,我們稱它為Observer,有時候我們也稱它為訂閱者,即Subscriber
- 被觀察者,我們稱它為Observable,即可以被觀察的東西,有時候還會稱之為主題,即Subject
至于觀察者模式的具體實現,java里為我們提供了Observable類和Observer接口供我們快速實現該模式,但是這里為了加深印象,不用這個兩個類
我們來模擬上邊的場景,先定義一個Weather的類
public class Weather {
private String description;
public Weather(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Weather{" +
"description='" + description + '\'' +
'}';
}
}
然后定義我們的被觀察著,我們希望它能夠通用,所以定義成泛型,內部應該暴露出register和unRegister供觀察者訂閱和取消訂閱,至于觀察者的保存,我們用ArrayList即可,另外,當主題發生變化的時候,需要通知觀察者來做出響應,還需要一個notifyObservers方法,具體實現如下:
public class Observable<T> {
List<Observer<T>> mObservers = new ArrayList<Observer<T>>();
public void register(Observer<T> observer) {
if (observer == null) {
throw new NullPointerException("observer == null");
}
synchronized (this) {
if (!mObservers.contains(observer))
mObservers.add(observer);
}
}
public synchronized void unregister(Observer<T> observer) {
mObservers.remove(observer);
}
public void notifyObservers(T data) {
for (Observer<T> observer : mObservers) {
observer.onUpdate(this, data);
}
}
}
而我們的觀察者只需要實現一個觀察者的接口Observer,該接口也是泛型的
public interface Observer<T> {
void onUpdate(Observable<T> observable,T data);
}
一旦訂閱的主題發生了變化,就會調用該接口
用一下,我們定義一個天氣變化的主題,也就是被觀察者,再定義兩個觀察者來觀察天氣的變化,一旦變化了就打印出天氣的情況,注意,一定要用register方法來注冊,否則觀察者收不到變化的信息,而一旦不感興趣,就可以調用unregister方法
public class Main {
public static void main(String [] args){
Observable<Weather> observable=new Observable<Weather>();
Observer<Weather> observer1=new Observer<Weather>() {
@Override
public void onUpdate(Observable<Weather> observable, Weather data) {
System.out.println("觀察者1:"+data.toString());
}
};
Observer<Weather> observer2=new Observer<Weather>() {
@Override
public void onUpdate(Observable<Weather> observable, Weather data) {
System.out.println("觀察者2:"+data.toString());
}
};
observable.register(observer1);
observable.register(observer2);
Weather weather=new Weather("晴轉多云");
observable.notifyObservers(weather);
Weather weather1=new Weather("多云轉陰");
observable.notifyObservers(weather1);
observable.unregister(observer1);
Weather weather2=new Weather("臺風");
observable.notifyObservers(weather2);
}
}
輸出也沒有問題
觀察者1:Weather{description=’晴轉多云’}
觀察者2:Weather{description=’晴轉多云’}
觀察者1:Weather{description=’多云轉陰’}
觀察者2:Weather{description=’多云轉陰’}
觀察者2:Weather{description=’臺風’}
好,我們來看一下在Android中的應用,從最簡單的開始,Button的點擊事件
Button btn=new Button(this);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("TAG","click");
}
});
另外廣播機制,本質也是觀察者模式
調用registerReceiver方法注冊廣播,調用unregisterReceiver方法取消注冊,之后使用sendBroadcast發送廣播,之后注冊的廣播會受到對應的廣播信息,這就是典型的觀察者模式
開源框架EventBus也是基于觀察者模式的,
觀察者模式的注冊,取消,發送事件三個典型方法都有
EventBus.getDefault().register(Object subscriber);
EventBus.getDefault().unregister(Object subscriber);
EventBus.getDefault().post(Object event);
4 、策略模式
定義:策略模式定義了一系列算法,并將每一個算法封裝起來,而且使他們可以相互替換,策略模式讓算法獨立于使用的客戶而獨立改變
最常見的就是關于出行旅游的策略模式,出行方式有很多種,自行車,汽車,飛機,火車等,如果不使用任何模式,代碼是這樣子的
public class TravelStrategy {
enum Strategy{
WALK,PLANE,SUBWAY
}
private Strategy strategy;
public TravelStrategy(Strategy strategy){
this.strategy=strategy;
}
public void travel(){
if(strategy==Strategy.WALK){
print("walk");
}else if(strategy==Strategy.PLANE){
print("plane");
}else if(strategy==Strategy.SUBWAY){
print("subway");
}
}
public void print(String str){
System.out.println("出行旅游的方式為:"+str);
}
public static void main(String[] args) {
TravelStrategy walk=new TravelStrategy(Strategy.WALK);
walk.travel();
TravelStrategy plane=new TravelStrategy(Strategy.PLANE);
plane.travel();
TravelStrategy subway=new TravelStrategy(Strategy.SUBWAY);
subway.travel();
}
}
很明顯,如果需要增加出行方式就需要在增加新的else if語句,這違反了面向對象的原則之一,對修改封裝(開放封閉原則)
題外話:面向對象的三大特征:封裝,繼承和多態
五大基本原則:單一職責原則(接口隔離原則),開放封閉原則,Liskov替換原則,依賴倒置原則,良性依賴原則
好,回歸主題,如何用策略模式來解決這個問題
首先,定義一個策略的接口
public interface Strategy {
void travel();
}
然后根據不同的出行方法來實現該接口
public class WalkStrategy implements Strategy{
@Override
public void travel() {
System.out.println("walk");
}
}
public class PlaneStrategy implements Strategy{
@Override
public void travel() {
System.out.println("plane");
}
}
public class SubwayStrategy implements Strategy{
@Override
public void travel() {
System.out.println("subway");
}
}
此外還需要一個包裝策略的類,來調用策略中的接口
public class TravelContext {
Strategy strategy;
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void travel() {
if (strategy != null) {
strategy.travel();
}
}
}
測試一下代碼:
public class Main {
public static void main(String[] args) {
TravelContext travelContext=new TravelContext();
travelContext.setStrategy(new PlaneStrategy());
travelContext.travel();
travelContext.setStrategy(new WalkStrategy());
travelContext.travel();
travelContext.setStrategy(new SubwayStrategy());
travelContext.travel();
}
}
以后如果再增加什么別的出行方式,就再繼承策略接口即可,完全不需要修改現有的類
策略模式優缺點
定義一系列算法:策略模式的功能就是定義一系列算法,實現讓這些算法可以相互替換。所以會為這一系列算法定義公共的接口,以約束一系列算法要實現的功能。如果這一系列算法具有公共功能,可以把策略接口實現成為抽象類,把這些公共功能實現到父類里面,對于這個問題,前面講了三種處理方法,這里就不羅嗦了。
避免多重條件語句:根據前面的示例會發現,策略模式的一系列策略算法是平等的,可以互換的,寫在一起就是通過if-else結構來組織,如果此時具體的算法實現里面又有條件語句,就構成了多重條件語句,使用策略模式能避免這樣的多重條件語句。
更好的擴展性:在策略模式中擴展新的策略實現非常容易,只要增加新的策略實現類,然后在選擇使用策略的地方選擇使用這個新的策略實現就好了。
客戶必須了解每種策略的不同:策略模式也有缺點,比如讓客戶端來選擇具體使用哪一個策略,這就可能會讓客戶需要了解所有的策略,還要了解各種策略的功能和不同,這樣才能做出正確的選擇,而且這樣也暴露了策略的具體實現。
增加了對象數目:由于策略模式把每個具體的策略實現都單獨封裝成為類,如果備選的策略很多的話,那么對象的數目就會很可觀。
只適合扁平的算法結構:策略模式的一系列算法地位是平等的,是可以相互替換的,事實上構成了一個扁平的算法結構,也就是在一個策略接口下,有多個平等的策略算法,就相當于兄弟算法。而且在運行時刻只有一個算法被使用,這就限制了算法使用的層級,使用的時候不能嵌套使用。
Android中的應用
下面說說在Android里面的應用。在Android里面策略模式的其中一個典型應用就是Adapter,在我們平時使用的時候,一般情況下我們可能繼承BaseAdapter,然后實現不同的View返回,GetView里面實現不同的算法。外部使用的時候也可以根據不同的數據源,切換不同的Adapter。
5、原型模式
定義:用原型實例指定創建對象的種類,并通過拷貝這些原型創建新的對象。
public class Person{
private String name;
private int age;
private double height;
private double weight;
public Person(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
", weight=" + weight +
'}';
}
}
要實現原型模式,按照以下步驟來:
1,實現一個Cloneable接口
public class Person implements Cloneable{
}
重寫Object的clone方法,在此方法中實現拷貝邏輯
@Override
public Object clone(){
Person person=null;
try {
person=(Person)super.clone();
person.name=this.name;
person.weight=this.weight;
person.height=this.height;
person.age=this.age;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
測試一下:
public class Main {
public static void main(String [] args){
Person p=new Person();
p.setAge(18);
p.setName("張三");
p.setHeight(178);
p.setWeight(65);
System.out.println(p);
Person p1= (Person) p.clone();
System.out.println(p1);
p1.setName("李四");
System.out.println(p);
System.out.println(p1);
}
}
輸出結果如下:
Person{name=’張三’, age=18, height=178.0, weight=65.0}
Person{name=’張三’, age=18, height=178.0, weight=65.0}
Person{name=’張三’, age=18, height=178.0, weight=65.0}
Person{name=’李四’, age=18, height=178.0, weight=65.0}
試想一下,兩個不同的人,除了姓名不一樣,其他三個屬性都一樣,用原型模式進行拷貝就會顯得異常簡單,這也是原型模式的應用場景之一
假設Person類還有一個屬性叫興趣集合,是一個List集合,就醬紫:
private ArrayList<String> hobbies=new ArrayList<String>();
public ArrayList<String> getHobbies() {
return hobbies;
}
public void setHobbies(ArrayList<String> hobbies) {
this.hobbies = hobbies;
}
在進行拷貝的時候就要注意了,如果還是跟之前的一樣操作,就會發現其實兩個不同的人的興趣集合的是指向同一個引用,我們對其中一個人的這個集合屬性進行操作 ,另一個人的這個屬性也會相應的變化,其實導致這個問題的本質原因是我們只進行了淺拷貝,也就是指拷貝了引用,最終兩個對象指向的引用是同一個,一個發生變化,另一個也會發生拜變化。顯然解決方法就是使用深拷貝
@Override
public Object clone(){
Person person=null;
try {
person=(Person)super.clone();
person.name=this.name;
person.weight=this.weight;
person.height=this.height;
person.age=this.age;
person.hobbies=(ArrayList<String>)this.hobbies.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
不再是直接引用,而是拷貝了一份,
其實有的時候我們看到的原型模式更多的是另一種寫法:在clone函數里調用構造函數,構造函數里傳入的參數是該類對象,然后在函數中完成邏輯拷貝
@Override
public Object clone(){
return new Person(this);
}
public Person(Person person){
this.name=person.name;
this.weight=person.weight;
this.height=person.height;
this.age=person.age;
this.hobbies= new ArrayList<String>(hobbies);
}
其實都差不多,只是寫法不一樣而已
現在 來看看Android中的原型模式:
先看Bundle類,
public Object clone() {
return new Bundle(this);
}
public Bundle(Bundle b) {
super(b);
mHasFds = b.mHasFds;
mFdsKnown = b.mFdsKnown;
}
然后是Intent類
@Override
public Object clone() {
return new Intent(this);
}
public Intent(Intent o) {
this.mAction = o.mAction;
this.mData = o.mData;
this.mType = o.mType;
this.mPackage = o.mPackage;
this.mComponent = o.mComponent;
this.mFlags = o.mFlags;
this.mContentUserHint = o.mContentUserHint;
if (o.mCategories != null) {
this.mCategories = new ArraySet<String>(o.mCategories);
}
if (o.mExtras != null) {
this.mExtras = new Bundle(o.mExtras);
}
if (o.mSourceBounds != null) {
this.mSourceBounds = new Rect(o.mSourceBounds);
}
if (o.mSelector != null) {
this.mSelector = new Intent(o.mSelector);
}
if (o.mClipData != null) {
this.mClipData = new ClipData(o.mClipData);
}
}
用法也十分簡單,一旦我們要用的Intent與現在的一個Intent很多東西都一樣,那我們就可以直接拷貝現有的Intent,再修改不同的地方,便可以直接使用
Uri uri = Uri.parse("smsto:10086");
Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri);
shareIntent.putExtra("sms_body", "hello");
Intent intent = (Intent)shareIntent.clone() ;
startActivity(intent);
網絡請求中最常用的OkHttp中,也應用了原型模式,就在OkHttpClient類中,他實現了Cloneable接口
/** Returns a shallow copy of this OkHttpClient. */
@Override
public OkHttpClient clone() {
return new OkHttpClient(this);
}
private OkHttpClient(OkHttpClient okHttpClient) {
this.routeDatabase = okHttpClient.routeDatabase;
this.dispatcher = okHttpClient.dispatcher;
this.proxy = okHttpClient.proxy;
this.protocols = okHttpClient.protocols;
this.connectionSpecs = okHttpClient.connectionSpecs;
this.interceptors.addAll(okHttpClient.interceptors);
this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
this.proxySelector = okHttpClient.proxySelector;
this.cookieHandler = okHttpClient.cookieHandler;
this.cache = okHttpClient.cache;
this.internalCache = cache != null ? cache.internalCache : okHttpClient.internalCache;
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.hostnameVerifier = okHttpClient.hostnameVerifier;
this.certificatePinner = okHttpClient.certificatePinner;
this.authenticator = okHttpClient.authenticator;
this.connectionPool = okHttpClient.connectionPool;
this.network = okHttpClient.network;
this.followSslRedirects = okHttpClient.followSslRedirects;
this.followRedirects = okHttpClient.followRedirects;
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
this.connectTimeout = okHttpClient.connectTimeout;
this.readTimeout = okHttpClient.readTimeout;
this.writeTimeout = okHttpClient.writeTimeout;
}
來自:http://blog.csdn.net/u012532559/article/details/52797809