模板模式源码级应用
模板模式我之前总结过
https://blog.csdn.net/u011109881/article/details/82453771
模板模式的思想:先在父类规定了具体的算法步骤以及算法顺序。父类可以给出部分步骤的具体实现,也可以都只给出方法框架,没有具体实现。在子类具体实现各个步骤的方法,但是各个步骤间的顺序在父类已经确定,子类无法通常不应该更改。如果规定算法顺序的方法在父类被定义成final,则子类就无法更改了。具体实现,子类可以根据实际需求确定是否修改。
模板方法的应用
1.AsyncTask的源码设计
之前也有过总结:
https://blog.csdn.net/u011109881/article/details/79943321
只不过当时并不知道AsyncTask有使用过模板设计模式
现在回过头看AsyncTask规定了自身执行的步骤:
onPreExecute doInBackground onPostExecute 子类或者说实现者可以根据自身需要在不同的步骤里面做想做的事情。这就是模板设计模式的思想
2.View的绘制流程
View的绘制流程我之前也有过总结
https://blog.csdn.net/u011109881/article/details/111148885
https://blog.csdn.net/u011109881/article/details/111188621
view的绘制流程里面有重要的三步,按先后顺序是ViewRootImpl中的
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
performDraw();
performMeasure内部会调用view的measure方法,measure方法内部又调用onMeasure方法
performLayout(lp, mWidth, mHeight);内部会调用view的layout方法,layout方法内部又调用onLayout方法
performDraw中兜兜转转最后还是调用了view的draw方法,draw方法内部又会调用onDraw方法
因此我们在自定义view的时候 通常可以通过覆盖onMeasure onLayout onDraw等方法来实现自定义view,其实父类以及规定好了步骤 我们只需要完善某一步骤。甚至说单单view的draw方法都是一个模板方法的使用 我们可以看看:
*/
@CallSuper
public void draw(Canvas canvas) {
final int privateFlags = mPrivateFlags;
mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
/*
* Draw traversal performs several drawing steps which must be executed
* in the appropriate order:
*
* 1. Draw the background
* 2. If necessary, save the canvas' layers to prepare for fading
* 3. Draw view's content
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
*/
// Step 1, draw the background, if needed
int saveCount;
drawBackground(canvas);
// skip step 2 & 5 if possible (common case)
final int viewFlags = mViewFlags;
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
// Step 3, draw the content
onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
drawAutofilledHighlight(canvas);
// Overlay is part of the content and draws beneath Foreground
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
// Step 7, draw the default focus highlight
drawDefaultFocusHighlight(canvas);
if (debugDraw()) {
debugDrawFocus(canvas);
}
// we're done...
return;
}
这里step1到7都是官方注释,这个其实就是模板方法 指定执行顺序
父类把step1 step2 等都定义好了,子类可以选择性覆盖这些方法
练练手 使用模板设计模式创建BaseActivity
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置布局layout
setContentView();
// 初始化头部
initTitle();
// 初始化界面
initView();
// 初始化数据
initData();
}
// 初始化数据
protected abstract void initData();
// 初始化界面
protected abstract void initView();
// 初始化头部
protected abstract void initTitle();
// 设置布局layout
protected abstract void setContentView();
/**
* 启动Activity
*/
protected void startActivity(Class<?> clazz){
Intent intent = new Intent(this,clazz);
startActivity(intent);
}
/**
* findViewById
* @return View
*/
protected <T extends View> T viewById(int viewId){
return (T) findViewById(viewId);
}
}
创建BaseActivity的好处有两点
1.规定了Activity的执行步骤,使得整个应用的Activity看起来比较一致,代码清晰
2.可以在BaseActivity实现一些Activity常用的方法, 避免每个Activity都去创建类似的方法,或者直接调用的时候产生冗余代码