实现一个简单的AsyncTask

如果你已经看过了上一篇博客:

Android异步任务–AsyncTask

那么你对AsyncTask的本质有了了解。它是对线程池加上Handler的封装,减少了开发者处理问题的复杂度,提高了开发效率。对Handler不是很了解的同学可以看一下:Android消息机制–Handler

下面我们就来简单的实现一个AsyncTask。类名为SimpleAsyncTask。与AsyncTask类似,我们提供三个函数,分别是onPerExecute、doInBackground、onPostExecute,不同的是我们这里只有一个代表doInBackground函数返回值类型的泛型参数。

它们的行为也与AsyncTask一致,即在onPreExecute函数在任务执行之前执行,且运行在UI线程中;doInBackground函数负责在后台执行任务并将结果返回;onPostExecute含有一个参数,这个参数就是doInBackground函数的返回值,onPostExecute也执行在UI线程中。SimpleAsyncTask代码如下:

/**
 * Created by aotu on 2018/2/8.
 */

public abstract class SimpleAsyncTask<Result> {
    //HandlerThread内部封装了自己的Handler和Thread,有单独的Looper和消息队列
    private static final HandlerThread HT = new HandlerThread("SimpleAsyncTask",
            Process.THREAD_PRIORITY_BACKGROUND);

    static {
        HT.start();
    }

    //获取调用execute的线程的Looper,构建Looper
    final Handler mUIHandler = new Handler(Looper.getMainLooper());
    //与异步线程队列相关联的Handler
    final Handler mAsyncTaskHandler = new Handler(HT.getLooper());

    /*
    * @功能描述:onPreExecute 任务执行之前的初始化等操作
    * */
    protected void onPreExecute() {
    }


    /*
    * doInBackground 后台执行任务
    * @return 返回执行结果
    * */
    protected abstract Result doInBackground();


    /*
    * doInBackground返回结果传递给执行在UI线程的onPostExecute
    * @param result 执行结果
    * */
    protected void onPostExecute(Result result) {
    }

    /*
    * execute 方法,执行任务,调用doInBackground,并且将执行结果投递给UI线程,使用户可以在onPostExecute处理结果
    * @return
    * */
    public final SimpleAsyncTask<Result>execute() {
        onPreExecute();
        //将任务投递到HandlerThread线程中执行
        mAsyncTaskHandler.post(new Runnable() {
            @Override
            public void run() {
                //后台执行任务,完成后向UI线程post数据,用以更新UI等操作
                postResult(doInBackground());
            }
        });
        return this;
    }

    private void postResult(final Result result) {
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                onPostExecute(result);
            }
        });
    }

}

在SimpleAsyncTask中我们创建了一个HandlerThread,HandlerThread是自带消息队列的Thread类型。当线程启动之后就会构件它的消息队列,因此在创建了HandlerThread对象之后,直接在静态代码块中启动了该线程。然后创建了两个Handler,它们分别为关联UI线程消息队列的mUIHandler和关联HandlerThread子线程的mAsyncTaskHandler。我们的doInBackground函数被一个Runnable包装并通过mAsyncTaskHandler投递给HandlerThread线程执行,当得到结果时又通过mUIHandler将结果投递一个Runnable,而这个Runnable中执行了SimpleAsyncTask的onPostExecute函数,因此,onPostExecute就执行在UI线程了。

下面我们使用SimpleAsyncTask:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new SimpleAsyncTask<String>() {
            private void makeToast(String msg){
                Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_SHORT).show();
            }

            @Override
            protected void onPreExecute() {
                makeToast("onPreExecute");
                Log.d("SimpleAsyncTask","onPreExecute");
            }

            @Override
            protected String doInBackground() {
                try{
                    Thread.sleep(3000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                Log.d("SimpleAsyncTask","doInBackground");
                return "doInBackground:HELLO WORLD!";
            }

            @Override
            protected void onPostExecute(String s) {
                Log.d("SimpleAsyncTask","onPostExecute");
                makeToast("onPostExecute:"+s);
            }
        }.execute();
    }
}

运行结果:

myasynctask我们在Logcat中看到:

logcat
log

OK,就到这里了。

PS:    祝大家新年快乐!工作顺利,学业有成!

 

发表评论

电子邮件地址不会被公开。

1 × 2 =