Template Method mode for Android source code analysis

Source: Internet
Author: User

Template Method mode for Android source code analysis
Mode definition

Defines the framework of an algorithm in an operation, and delays some steps to the subclass. This allows subclass to redefine certain steps of an algorithm without changing the structure of an algorithm.


Use Cases

1. Multiple subclasses have public methods, and the logic is basically the same.

2. for important and complex algorithms, the Core algorithms can be designed as template methods, and the surrounding detailed functions are implemented by sub-classes.

3. During refactoring, the template method mode is a frequently used mode, which extracts the same code into the parent class and then limits its behavior through the hook function.


UML class diagram



Roles

AbstractClass: abstract class, which defines a set of algorithm frameworks.

ConcreteClass1: Implementation Class 1;

ConcreteClass2: Implementation Class 2;


Simple Example

The template method encapsulates an algorithm framework, just like a set of templates. Child classes can have different algorithm implementations. They can be replaced without being modified by the framework. The following is a simple demonstration of the template method by running the computer. The entire process of enabling a computer is relatively stable. First, turn on the computer power, and the computer will enter the operating system when detecting its status is normal. After verifying the user, you can log on to the computer, below we use the template method to simulate this process.

Package com. dp. example. templatemethod;/*** abstract Computer * @ author mrsimple **/public abstract class implements actcomputer {protected void powerOn () {System. out. println ("power on");} protected void checkHardware () {System. out. println ("hardware check");} protected void loadOS () {System. out. println ("load operating System");} protected void login () {System. out. println ("white computer without verification, directly go to the system");}/*** start the computer method, the steps are fixed to turn on the power, system check, load the operating system, use User logon. This method is final to prevent the algorithm framework from being overwritten. */public final void startUp () {System. out. println ("------ START ------"); powerOn (); checkHardware (); loadOS (); login (); System. out. println ("------ start END ------") ;}} package com. dp. example. templatemethod;/*** code farmer's computer ** @ author mrsimple */public class CoderComputer extends AbstractComputer {@ Override protected void login () {System. out. println ("codefarm only needs to verify the user and password") ;}} package com. dp. example. templatemethod;/*** military computer *** @ author mrsimple */public class MilitaryComputer extends AbstractComputer {@ Override protected void checkHardware () {super. checkHardware (); System. out. println ("Check hardware firewall") ;}@ Override protected void login () {System. out. println ("complex user verification like fingerprint verification") ;}} package com. dp. example. templatemethod; public class Test {public static void main (String [] args) {AbstractComputer comp = new CoderComputer (); comp. startUp (); comp = new MilitaryComputer (); comp. startUp ();}}

The output is as follows:

------ Boot START ------ enable power hardware check load operating system code farmers only need to verify the user and password ------ boot END ---------- boot START ------ enable power hardware check hardware firewall load operating system fingerprint and other complex user verification ------ start END ------

The above example shows that there are some fixed steps in the startUp method, which are four steps: power on, hardware check, system loading, and user logon, these four steps are not changed during the computer boot process. However, different users may have different implementations of these steps, so they can use different implementations. StartUp is the final method, which ensures that the algorithm framework cannot be modified, but the specific algorithm implementation can be changed flexibly. The algorithm steps in startUp can be called a routine or a template method. Therefore, the template method defines the framework of an algorithm in an operation, and delays some steps to the subclass. This allows subclass to redefine certain steps of an algorithm without changing the structure of an algorithm. :



Source code analysis

In Android, the template method is used and a typical class we are familiar with is AsyncTask. For more detailed analysis of AsyncTask, see the use of AsyncTask and source code analysis in Android, here we only analyze the template method modes used in this class.

When using AsyncTask, we all know that time-consuming methods should be placed in doInBackground (Params... in params), if you want to perform initialization-like operations before doInBackground, you can write them in the onPreExecute method. After the doInBackground method is executed, the onPostExecute method is executed, instead, we only need to build the AsyncTask object and then execute the execute method. We can see that the entire execution process is actually a framework, and the specific implementation needs to be completed by sub-classes. In addition, the algorithm framework it executes is fixed. After the execute Command is called, onPreExecute, doInBackground, and onPostExecute are executed in sequence. Of course, you can update the progress through onProgressUpdate. We can simply understand the mode as follows:


Let's look at the source code. First, let's look at the entry for executing asynchronous tasks, that is, the execute method:

 public final AsyncTask
 
   execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }    public final AsyncTask
  
    executeOnExecutor(Executor exec,            Params... params) {        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)");            }        }        mStatus = Status.RUNNING;        onPreExecute();        mWorker.mParams = params;        exec.execute(mFuture);        return this;    }
  
 
We can see that the execute method (a final method) calls the executeOnExecutor method. In this method, the status of the task is determined. If it is not the PENDING status, an exception is thrown, this also explains why AsyncTask can only be executed once, so if the task has been executed, its status will change to FINISHED. Further, we can see that the onPreExecute method is first executed in the executeOnExecutor method, and the method is executed in the UI thread. Afterwards, paramsparameters are passed to the mparams field of the mworkerobject, And the exec.exe cute (mFuture) method is executed later.

What is mWorker and mFuture? In fact, mWorker only implements the Callable interface and adds a parameter array field. For details about Callable and FutureTask, see the differences and examples of Runnable, Callable, Future, and FutureTask in Java, let's analyze them one by one. We can see from the trace code that these two fields are initialized in the constructor,

   public AsyncTask() {        mWorker = new WorkerRunnable
 
  () {            public Result call() throws Exception {                mTaskInvoked.set(true);                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                return postResult(doInBackground(mParams));            }        };        mFuture = new FutureTask
  
   (mWorker) {            @Override            protected void done() {                try {                    final Result result = get();                    postResultIfNotInvoked(result);                } catch (InterruptedException e) {                    android.util.Log.w(LOG_TAG, e);                } catch (ExecutionException e) {                    throw new RuntimeException("An error occured while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                } catch (Throwable t) {                    throw new RuntimeException("An error occured while executing "                            + "doInBackground()", t);                }            }        };    }
  
 
In short, mFuture encapsulates the mWorker object, calls the call method of the mWorker object, and returns it to the caller.

For more detailed analysis of AsyncTask, see the use of AsyncTask and source code analysis in Android. Here we only analyze the template method mode. In short, the call method is called in the subthread, And the doInBackground method is called in the call method. Therefore, the doInBackground method is executed in the subthread. DoInBackground returns the result and finally delivers it to the UI thread through postResult.

Let's look at the implementation of postResult:

    private Result postResult(Result result) {        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult
 
  (this, result));        message.sendToTarget();        return result;    }    private static class InternalHandler extends Handler {        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})        @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);        }        mStatus = Status.FINISHED;    }
 

As you can see, postResult refers to a message (msg. what = MESSAGE_POST_RESULT) is sent to sHandler, And the sHandler type is InternalHandler. When InternalHandler receives a message of the MESSAGE_POST_RESULT type, it calls result. mTask. finish (result. mData [0]) method. We can see that the result type is AsyncTaskResult. The source code is as follows:
@SuppressWarnings({"RawUseOfParameterizedType"})    private static class AsyncTaskResult {        final AsyncTask mTask;        final Data[] mData;        AsyncTaskResult(AsyncTask task, Data... data) {            mTask = task;            mData = data;        }    }
We can see that mTask is the AsyncTask object. When the finish method of the AsyncTask object is called, onPostExecute is called again. At this time, the entire execution process is completed.

In short, the execute method encapsulates the onPreExecute, doInBackground, and onPostExecute Algorithm Framework. You can override these methods as needed, this allows you to conveniently use Asynchronous tasks to perform time-consuming operations, and update the UI thread through onPostExecute.


Advantages and disadvantages: 1. encapsulate the unchanged part, expand the variable part 2. Extract the common part of the code for easy maintenance
Disadvantage: The template method makes it difficult to read the code and hard to understand.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.