模板模式
模板模式在Android源码中出现的很多,比如Activity和Srervice的生命周期,启动过程,还有AsyncTask类等。模板模式可以理解为一种算法流程的集合,可以通过构造函数来灵活控制流程,实现抽象方法,来具体化细节。
使用
1.具有相似流程的算法,可以考虑抽象出模板。 2.在重构过程中,可以把相似的子类抽象出一个模板父类,比如我们Android的BaseActivity和BaseAdapter等抽象类。
官方定义
定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
通俗点的理解就是 :完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。
结构
1.抽象父类 2.具体的子类
优缺点
模板模式的优点
(1)具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构。
(2)代码复用的基本技术,在数据库设计中尤为重要。
(3)存在一种反向的控制结构,通过一个父类调用其子类的操作,通过子类对父类进行扩展增加新的行为,符合“开闭原则”。
缺点
每个不同的实现都需要定义一个子类,会导致类的个数增加,系统更加庞大。
在Android源码中的使用
1.系统启动过程,具体参考这篇博客: https://juejin.im/post/5b3885d96fb9a00e687a0708 2.组件生命周期,比如Activity和Service等 3.一些具体封装类,比如AsyncTask等
举例AsyncTask Android源码
首先众所周知,AsyncTask的模板就是那几个抽象方法,等你去实现,我们每次使用这个类,就是实现一个具体的子类,而且一个对象只能用一次,为什么呢?我们下面一一解开
模板
1.onPreExecute() 2.doInBackground() 3.onProgressUpdate() 4.onPostExecute()
抽象父类的细节
首先介绍几个角色: 1.ThreadPool:AsyncTask默认用线程池来切换线程,这个线程池在不通Android版本是不一样的,最初始串行的,后来是并行,现在又是串行,是一个全局的线程池。
2.Handler:这个用于线程的消息交互,主要是子线程通知到UI线程,因为onPostEx’ecute()是在UI线程,所以我们handler必须在U线程初始化。
为什么AsyncTask必须在UI线程初始化呢?
就是以为内部的Handler必须是绑定UI线程的,而这个handler绑定的线程是也是在AsyncTask初始化的当前线程。
介绍模板调用细节
1.首先执行AsyncTask.Execute(Params)
这个方法会调用ExecuteOnExecutor(Executor,Params),会传入默认的线程池:sDefaultExecutor和参数
2.ExecuteOnExecutor(Executor,Params)
这个方法会做以下几件事: 1.开始判断AsyncTask对象是否处于Running和Finish状态,如果是就会弹出异常。然后设定这个AsyncTask对象处于running状态。这也是为什么一个AsyncTask对象只能用一次。
2.调用onPreExecute()做一些初始化和准备。
3.调用doInBackground,初始化mWorker,并把Params赋值给mWorker的mParams成员。mWorker实现了Callable接口并在视线中调用了postResult(doInBackground(Params)),这个方法是关键,完成了线程切换,我们后面展开讲。
4.初始化mFuture,这是一个FutureTask对象,可以理解为一个Thread对象。
5.sDefaultExecutor.execute(mFuture),mFuture的run()方法会调用mWorker的call回调方法,最终调用postResult(doInBackground(Params))
postResult(doInBackground(Params))方法
以上是onPreExecute()和doInBackground()方法已经被调用了
postResult(doInBackground(Params))这个方法做了一下几个事: 1.构造一个AsyncTaskResult,这个对象是两个对象构造: AsyncTask对象实例 doInBackground执行完的Result
2.构造一个UI线程Handler的Message,what是MESSAGE_POST_RESULT,obj是AsyncTaskResult
3.发送给UI线程Handler处理。这个handler能处理两类消息就是: MESSAGE_POST_RESULT:收到这个消息后切换到UI线程,取出obj里面的AsyncTask对象实例调用finish()方法,finish方法会调用onPostExecute()犯法,并且把状态标为finish。 MESSAGE_POST_PROGRESS消息: 会调用AsyncTask对象实例的onUpdateProgress()方法
结束
模板模式在Android源码架构层面也处处可见,如果你留意就会经常发现它的身影。