Android设计模式——模板模式

mac2022-06-30  99

Android设计模式——模板模式

1.模板模式定义2.模板使用场景3.源码中用到的模板设计模式3.1 Activity的生命周期采用了模板设计模式3.2 AsyncTask也采用了模板设计模式3.3 AsyncTask简单使用3.4 AsyncTask源码简单分析 4.线程池介绍5.常用的BaseActivity模板模式6.UML图

1.模板模式定义

  定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。说白了就是必须得有继承,父类一般都是流程和通用部分的封装,子类一般都是实现父类的方法,然后实现自己具体的功能;

2.模板使用场景

  1.多个子类有公共的方法,并且逻辑进本相同   2.重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数来约束其行为。

3.源码中用到的模板设计模式

3.1 Activity的生命周期采用了模板设计模式

  都是继承自Activity ,内部封装一套具体的流程,onCreate – onStart – onResume… 只需要我们继承Activity,可以自己设置自己的布局,自己实现具体的逻辑代码。

3.2 AsyncTask也采用了模板设计模式

  AsyncTask实现原理:线程池 + Handler   早期我们使用网络请求都是AsyncTask,它内部也是一套具体的流程,onPreExecute – doInBackground – onPostExecute … 只需我们继承AsyncTask,可以自己实现网络请求耗时操作。

3.3 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); } } }

3.4 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); } ... }

6.UML图

最新回复(0)