提示: 注意到 TextView 控制項設定文本時的參數有TextView.BufferType.EDITABLE 和 TextView.BufferType.SPANNABLE
但是不知道具體啥差別, 於是決定窺探 Google 代碼,看個究竟。
一、在 TextView 類中找到 setText 方法關於 BufferType 的主要代碼:
Java代碼
// Editable 是一個介面,作者巧妙的在介面中實現了Factory 方法。
private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
// Editable 是一個介面,作者巧妙的在介面中實現了Factory 方法。
private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
Java代碼
if (type == BufferType.EDITABLE || mInput != null ||
needEditableForNotification) {
Editable t = mEditableFactory.newEditable(text);
text = t;
setFilters(t, mFilters);
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) imm.restartInput(this);
} else if (type == BufferType.SPANNABLE || mMovement != null) {
text = mSpannableFactory.newSpannable(text);
} else if (!(text instanceof CharWrapper)) {
text = TextUtils.stringOrSpannedString(text);
}
if (type == BufferType.EDITABLE || mInput != null ||
needEditableForNotification) {
Editable t = mEditableFactory.newEditable(text);
text = t;
setFilters(t, mFilters);
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) imm.restartInput(this);
} else if (type == BufferType.SPANNABLE || mMovement != null) {
text = mSpannableFactory.newSpannable(text);
} else if (!(text instanceof CharWrapper)) {
text = TextUtils.stringOrSpannedString(text);
}
可以看出根據不同 BufferType ,用類工廠的模式建立控制項,那麼為什麼不直接 new 一個控制項呢?首先想到的是減少與實作類別的耦合,提高可維護性。
二、帶著上面的問題,在 TextView 類中找到下面的代碼,提供了更換 Factory 的可能,使得開發人員方便做不同的控制項實現。
Java代碼
public final void setEditableFactory(Editable.Factory factory) {
mEditableFactory = factory;
setText(mText);
}
public final void setSpannableFactory(Spannable.Factory factory) {
mSpannableFactory = factory;
setText(mText);
}
public final void setEditableFactory(Editable.Factory factory) {
mEditableFactory = factory;
setText(mText);
}
public final void setSpannableFactory(Spannable.Factory factory) {
mSpannableFactory = factory;
setText(mText);
}
三、那麼如何自訂控制項的實現呢,需要新寫一個介面繼承 Editable, 並且覆蓋掉 Editable 中下面的方法:
Java代碼
public static class Factory {
private static Editable.Factory sInstance = new Editable.Factory();
public static Editable.Factory getInstance() {
return sInstance;
}
public Editable newEditable(CharSequence source) {
return new SpannableStringBuilder(source);
}
}
public static class Factory {
private static Editable.Factory sInstance = new Editable.Factory();
public static Editable.Factory getInstance() {
return sInstance;
}
public Editable newEditable(CharSequence source) {
return new SpannableStringBuilder(source);
}
}
四、TextView.BufferType.EDITABLE 和 TextView.BufferType.SPANNABLE
有什麼區別呢?我們透過UML瞧一下, Editable 類似於StringBuilder可追加字元,
也就是說getText後可調用append方法設定常值內容。Spannable 則可在給定的字元地區使用樣式。有意思的是 Editable 繼承了 Spannable 所以具備較多的功能。
摘自 藍色理想——帥子