android异步机制

来源:互联网 发布:spss19.0 for mac下载 编辑:程序博客网 时间:2024/05/20 18:44

概述:

异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。

handler机制

一、使用的优点:

          结构清晰,功能定义明确
          对于多个后台任务时,简单,清晰
       使用的缺点:

          在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)


二、Handler 、 Looper 、Message 这三者的关系总结:
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
好了,总结完成,大家可能还会问,那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。


三、Looper主要作用:
        与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
        loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
        private Looper(boolean quitAllowed) {  
                mQueue = new MessageQueue(quitAllowed);  
                mRun = true;  
                mThread = Thread.currentThread();  
        }  
        在构造方法中,创建了一个MessageQueue(消息队列)。
        public static final void prepare() {  
            if (sThreadLocal.get() != null) {  
                throw new RuntimeException("Only one Looper may be created per thread");  
            }  
            sThreadLocal.set(new Looper(true));  
        }  
        这也就说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper实例。


四、在子线程中创建handler:

其实Handler不仅可以更新UI,你完全可以在一个子线程中去创建一个Handler,然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。
    new Thread(){  
        private Handler handler;  
        public void run()  
        {  
            Looper.prepare();   
            handler = new Handler()  
            {  
                public void handleMessage(android.os.Message msg)  
                {  
                    Log.e("TAG",Thread.currentThread().getName());  
                };  
            };



android.os.AsyncTask

一、使用的优点: 简单,快捷 、过程可控      
        使用的缺点:在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.


二、主要方法介绍:

     doInBackground(Params…)  后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
    onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
    onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
    onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
    onCancelled()  用户调用取消时,要做的操作


三、使用AsyncTask类,以下是几条必须遵守的准则:
    Task的实例必须在UI thread中创建;
    execute方法必须在UI thread中调用;
    不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
    该task只能被执行一次,否则多次调用时将会出现异常;


四、实例说明:

创建一个asynctask:

/** * 执行的顺序: *      onPreExecute() ---> doInBackground() ---> publishProgress() ---> onProgressUpdate() ....---> onPostExecute() * ...表示:publishProgress() ---> onProgressUpdate() */public class MyAsyncTask extends AsyncTask<Integer , Object , String>{    private TextView tv;    public MyAsyncTask(TextView textView){        Log.e(TAG , "调用到了构造函数");        this.tv = textView;    }    /**     * 这里的Integer参数对应AsyncTask中的第一个参数     * 这里的String返回值对应AsyncTask的第三个参数     * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改     * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作     */    @Override    protected String doInBackground(Integer[] params) {        int i;        for (i = 0; i <= 100; i++) {            publishProgress(i); //会将这个值传递给onProgressUpdate()方法            SystemClock.sleep(1000);        }        Log.e(TAG , "调用到了doInBackground  i = " + i );        return i + "";    }    /**     * 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。     */    @Override    protected void onPreExecute() {        Log.e(TAG , "调用到了onPreExecute");        super.onPreExecute();        tv.setText("开始执行异步操作了");    }    /**     * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)     * 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置     */    @Override    protected void onPostExecute(String result) {        Log.e(TAG , "调用到了onPostExecute result = " + result );        super.onPostExecute(result);        tv.setText(result);    }    /**     * 这里的Intege参数对应AsyncTask中的第二个参数     * 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行     * onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作     */    @Override    protected void onProgressUpdate(Object... values) {        Log.e(TAG , "调用到了onProgressUpdate value = " + values);        super.onProgressUpdate(values);        tv.setText(values[0] + "");    }}



执行异步操作:

MyAsyncTask task = new MyAsyncTask(tv_show);task.execute();


0 0
原创粉丝点击