Android设计模式——模板模式

2019-10-01  本文已影响0人  如愿以偿丶

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个线程任务

线程池1.gif

可能会疑问 “线程池核心数量” 和 “线程池最大数量” 有什么区别。我们修改一下缓存队列数量。修改为10,看下执行结果。

线程池2.gif
解析:
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);
    }
    ...
}
上一篇 下一篇

猜你喜欢

热点阅读