[mobilesafe] 01_抽象模板方法-异步任务

Android 4.0

抽象模板方法-异步任务

一、模板方法前:
package cn.zengfansheng.asynctask;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    private ProgressDialog pd;
    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            // 3、数据获取完毕,处理子线程中发来的ui更新消息,主线程
            pd.dismiss();
        };
    };
    /**
     * 执行异步任务
     * @param view
     */
    public void click(View view) {
        // 1、获取数据前,更新ui,主线程
        // pd = new ProgressDialog(getApplicationContext());
        pd = new ProgressDialog(this);
        pd.setTitle("温馨提醒:");
        pd.setMessage("正在获取数据:请稍等");
        pd.show();
        
        // 2、开启子线程获取数据,这个过程漫长,需要在子线程中,获取数据完毕发送消息更新ui
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendEmptyMessage(0);
            }
        }.start();
    }
}
二、使用模板方法后:
1、模板类:MyAsyncTask.java
package cn.zengfansheng.asynctask;
import android.os.Handler;
import android.os.Message;
/**
 * 模板方法
 * @author hacket
 */
public abstract class MyAsyncTask {
    /**
     * 1、在后台执行任务之前执行的方法,用来更新UI,主线程
     */
    protected abstract void onPreExecute();
    /**
     * 3、在后台执行任务之后执行的方法,更新UI,主线程
     */
    protected abstract void onPostExecute();
    /**
     * 2、在后台执行任务时执行的方法,运行在子线程中,如:获取数据
     */
    protected abstract void doInBackgroundExecute();
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            // 3、获取数据完毕,更新ui
            onPostExecute();
        }
    };
    /**
     * 4、对外暴露的方法
     */
    protected void execute() {
        // 1、获取数据前,更新ui
        onPreExecute();
        // 2、后台获取数据,更新ui
        new Thread() {
            public void run() {
                doInBackgroundExecute();
                handler.sendEmptyMessage(0);
            }
        }.start();
    }
}
2、MainActivity.java
package cn.zengfansheng.asynctask;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    /**
     * 执行异步任务
     * @param view
     */
    public void click(View view) {
        // 使用模板来执行任务
        new MyAsyncTask() {
            private ProgressDialog pd;
            @Override
            protected void onPreExecute() {
                pd = new ProgressDialog(MainActivity.this);
                pd.setTitle("温馨提醒:");
                pd.setMessage("正在获取数据:请稍等");
                pd.show();
            }
            @Override
            protected void onPostExecute() {
                pd.dismiss();
            }
            @Override
            protected void doInBackgroundExecute() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.execute();
    }
}
结果:
三、解决msg.what : 多个消息的问题  MyAsyncTask.java
package cn.zengfansheng.asynctask;
 
import android.os.Handler;
import android.os.Message;
 
/**
* 模板方法
* @author hacket
*/

public abstract class MyAsyncTask {
 
    protected static final int EXECUTE_FINISHED = 1;// 执行完毕
    private static final int ONPROGRESS = 2;// 更新过程中
 
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
            case EXECUTE_FINISHED:// 执行完毕,更新ui
                // 3、获取数据完毕,更新ui
                onPostExecute();
                break;
            case ONPROGRESS:// 正在执行子线程 需要获取进度
                int progress = (Integer) msg.obj;
                onProgressUpdate(progress);// 当调用了publishProgress发布进度,也就是发送了消息,这里就执行ui变化。
                break;
            }
        }
    };
 
    /**
     * 1、在后台执行任务之前执行的方法,用来更新UI,主线程
     */

    protected abstract void onPreExecute();
 
    /**
     * 3、在后台执行任务之后执行的方法,更新UI,主线程
     */

    protected abstract void onPostExecute();
 
    /**
     * 2、在后台执行任务时执行的方法,运行在子线程中,如:获取数据
     */

    protected abstract void doInBackgroundExecute();
 
    /**
     * 4、进度更新的时候执行的方法,运行在主线程
     * @param progress 进度值
     */

    protected abstract void onProgressUpdate(int progress);
 
 
    /**
     * 5、发布子线程执行的进度
     * @param progres 发布的进度值
     */

    protected void publishProgress(int progress) {
        Message msg = Message.obtain();
        msg.obj = progress;
        msg.what = ONPROGRESS;
        handler.sendMessage(msg);
    }
 
    /**
     * 6、对外暴露的方法,执行异步任务
     */

    protected void execute() {
        // 1、获取数据前,更新ui
        onPreExecute();
 
        // 2、后台获取数据,更新ui
        new Thread() {
            public void run() {
                doInBackgroundExecute();
                handler.sendEmptyMessage(EXECUTE_FINISHED);
            }
        }.start();
    }
}
2、MainActivity.java
package cn.zengfansheng.asynctask;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) this.findViewById(R.id.tv);
    }

    /**
     * 执行异步任务
     * @param view
     */

    public void click(View view) {


        // 使用模板来执行任务
        new MyAsyncTask() {
            private ProgressDialog pd;

            @Override
            protected void onPreExecute() {
                pd = new ProgressDialog(MainActivity.this);
                pd.setTitle("温馨提醒:");
                pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                pd.setMessage("正在获取数据:请稍等");
                pd.show();
            }

            @Override
            protected void onPostExecute() {
                pd.dismiss();
            }

            @Override
            protected void doInBackgroundExecute() {
                try {
                    pd.setMax(100);
                    for (int i = 1; i <= 100; i++) {
                        Thread.sleep(40);
                        publishProgress(i);// 每次更新数据时,都调用publishProgress,来发布最新的进展,其实就是发送消息,更新ui
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            protected void onProgressUpdate(int progress) {
                pd.setProgress(progress);
                // tv.setText(progress);//由于是int,会当前资源文件,所以被报错资源找不到的异常。
                tv.setText("当前进度:" + progress + "%");
            }

        }.execute();
    }
}
结果:
问题1:pd = new ProgressDialog(getApplicationContext()); 
分析:ProgressDialog要依附一个Activity给显示,如果是一个Context,代表整个Application。
解决: pd = new ProgressDialog(this);   
11-21 16:48:15.480: E/AndroidRuntime(20253): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application