1.模板模式定义
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。说白了就是必须得有继承,父类一般都是流程和通用部分的封装,子类一般都是实现父类的方法,然后实现自己具体的功能;
2.模板使用场景
1.多个子类有公共的方法,并且逻辑进本相同
2.重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数来约束其行为。
3.源码中用到的模板设计模式
3.1 Activity的生命周期采用了模板设计模式
都是继承自Activity ,内部封装一套具体的流程,onCreate -- onStart -- onResume... 只需要我们继承Activity,可以自己设置自己的布局,自己实现具体的逻辑代码。
3.2.AsyncTask也采用了模板设计模式
AsyncTask实现原理:线程池 + Handler
早期我们使用网络请求都是AsyncTask,它内部也是一套具体的流程,onPreExecute -- doInBackground -- onPostExecute ... 只需我们继承AsyncTask,可以自己实现网络请求耗时操作。
AsyncTask简单使用
public class AsyncTaskActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task);
//调用
new Task().execute();
}
public class Task extends AsyncTask<Void,Void,Void> {
/**
* 第一个执行的方法
* 执行在主线程中,做一些准备工作,可以显示进度条,也可以不做处理
*/
@Override
protected void onPreExecute() {
Log.e("TAG","onPreExecute");
Log.e("onPreExecute",Thread.currentThread()+"");
super.onPreExecute();
}
/**
* 做耗时操作,执行在子线程中 线程池
* @param voids
* @return
*/
@Override
protected Void doInBackground(Void... voids) {
Log.e("TAG","doInBackground");
Log.e("doInBackground",Thread.currentThread()+"");
return null;
}
/**
* 最终执行完成 通过Handler进行线程切换
* @param aVoid
*/
@Override
protected void onPostExecute(Void aVoid) {
Log.e("TAG","onPostExecute");
Log.e("onPostExecute",Thread.currentThread()+"");
super.onPostExecute(aVoid);
}
}
}
image.png
AsyncTask源码简单分析
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
//设置标志位,每个请求只能执行一次。执行完成会将状态置为 FINISHED
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
//默认为RUNNING
mStatus = Status.RUNNING;
//第一个方法,做一些初始化操作
onPreExecute();
mWorker.mParams = params;
// 线程池,存放Runnable
exec.execute(mFuture);
return this;
}
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Result result = null;
try {
// doInBackground 执行在子线程中
result = doInBackground(mParams);
} finally {
//最终调用该方法,通过Handler切换线程
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
....
}
};
}
// 通过Handler 切换到主线程中
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private static class InternalHandler extends Handler {
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
//取消
onCancelled(result);
} else {
// 执行完成
onPostExecute(result);
}
// 将状态置为FINISHED
mStatus = Status.FINISHED;
}
4.线程池介绍
线程执行时间:t = t1(线程的创建时间) + t2(run方法执行时间) + t3(线程的销毁时间),所有当我们需要反复创建线程就可以使用线程池。
线程池作用:线程池是去解决线程反复的创建和销毁,解决线程反复的使用。
public class AsyncTaskTest {
private static ThreadPoolExecutor threadPoolExecutor;
//缓存队列 设置最大数量
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(40);
static {
threadPoolExecutor = new ThreadPoolExecutor(
5, //核心线程数量,就是线程池中核心线程数量
10, //线程池最大线程数,就是线程池中最大线程数
30, //线程存活时间
TimeUnit.SECONDS, //时间单位 秒,毫秒等
sPoolWorkQueue, //缓存队列
new ThreadFactory() { //线程工厂,当我们线程池中需要创建线程就会调用newThread来创建, 为什恶魔不写死,因为有时候我们要给线程设置参数name
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r,"自己线程的名字");
thread.setDaemon(false); //设置不是守护线程
// return thread;
return new Thread(r);
}
});
}
public static void main(String[] args){
for (int i = 0; i < 30; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("下载完成"+Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
};
//加入线程队列寻找合适的时机去执行
threadPoolExecutor.execute(runnable);
}
}
}
执行结果:
每隔2秒都会执行5个线程任务
可能会疑问 “线程池核心数量” 和 “线程池最大数量” 有什么区别。我们修改一下缓存队列数量。修改为10,看下执行结果。
解析:
1.线程池中最大核心数是5
2.线程池最大线程数量是10
3.缓存队列数量为10
4.要执行的Runnable为30
报错原因:首先要执行的Runnabler为30个,30个都要放到队列中,而缓存队列中最多只能存放10个,还有20个没法放,这个时候最大线程数是10,非核心线程数也是5,此时就会拿5个Runnabler来执行,会创建5个非核心线程,目前线程池中达到了10个线程,但是还有20个没法存放,也就意味着20个Runnable没办法执行,此时就会报错。
常用的缓存池:
BlockingQueue:先进先出的一个队列。
SynchronousQueue:线程安全队列,他里面没有固定的缓存的(okhttp使用的)
PriorityBlockingQueue:无序的根据优先级进行排序,执行对象要实现Comparable 作比较
5.常用的BaseActivity模板模式
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.设置布局
setContentView();
//2.初始化View
initView();
//3.初始化Title
initTitle();
//4.访问网络接口数据
initData(savedInstanceState);
}
protected abstract void initData(Bundle savedInstanceState);
protected abstract void initTitle();
protected abstract void initView();
protected abstract void setContentView();
public void startActivity(Class<? extends BaseActivity> clazz){
Intent intent = new Intent(this,clazz);
startActivity(intent);
}
...
}
网友评论