android开发学习--AsyncTask

Android的UI线程主要负责处理用户的按键事件、用户触屏事件及屏幕绘图事件等,对于其他的操作尽量不要在UI线程中实现,因为这些操作很有可能会阻塞UI线程,导致UI界面停止响应,从而降低了用户的体验,严重时出现ANR(无响应)。为了避免UI线程失去响应的问题,Android建议将耗时操作移动到新线程中完成,但新线程也可能需要动态更新UI组件(比如需要从网上获取一个网页,然后在TextView中将其源代码显示出来,此时就应该将连接网络,获取网络数据的操作放在新线程中完成.)为此Android封装了一个简单实用的异步任务类AsyncTask来负责耗时任务的 处理,同时方便后台线程和UI线程进行通讯。

先来看看AsyncTask的定义:

public abstract class AsyncTask<Params, Progress, Result> { 
//A client will call this method
AsyncTask<Params,Progress,Result>
excute(Params...Params);

//Do your work here
//Frequently trigger onProgressUpdate()
Result doInBackGround(Params...params);

//Callback: After the work is complete
void onPostExecute(Result result);

//Callback:As the work is progressing
void OnProgressUpdate(Progress...progressValueArray);}

三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。在特定场合下,并不是所有类型都被使用,如果没有被使用,可以用java.lang.Void类型代替。
1、excute方法的参数类型:在扩展AsynTask时需要指出要传递给excute方法的参数类型,假设类型为string,那么调用时要求各个字符串由逗号隔开
2、onProgressUpdate方法的参数类型:报告进度时向调用者回传的数值类型,支持数组。满足在异步任务中存在多个子任务的场景。
3、onPostExecute方法的参数类型:异步任务执行最终的返回结果类型。
2.Async类方法
(1)onPreExecute():
功能:做一些任务执行前的初始化工作,如在界面上展示一个进度条等
执行时机:执行实际工作前被UI线程调用。
(2)doInBackground(Params…values):
功能:负责执行比较耗时的处理工作,并通过publishProgress()将任务处理进度通知至UI线程。子类必须实现该方法。
执行时机:onPreExcute()函数之后被调用,在工作线程被执行。
(3)onProgressUpdate(Progress…values):
功能:定期的向UI线程反馈任务执行的进度。
执行时机:运行在UI线程。
(4)onPostExecute(Result):
功能:将工作线程的执行结果返回给UI线程。
执行时机:doInBackground()函数的执行结果返回给UI线程。运行在UI线程。
(5) onCancelled():
功能:取消后台工作线程。在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
执行时机:UI线程调用。
注意:
另外,使用AsyncTask类需要遵守的以下准则:
(1)AsyncTask的实例必须在UI线程中创建;
(2)execute(Params…)方法必须在UI线程中调用;
(3)禁止调用onPreExecute(), onPostExecute(Result),doInBackground(Params…),onProgressUpdate(Progress…)方法;
(4)每个AsynTask只允许被执行一次,多次调用时将会出现异常。
3、AsyncTask用法实战

package com.example.AsyncTask;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
//import android.widget.ProgressBar;
import android.widget.TextView;
import android.view.View;
import android.util.Log;

import android.os.AsyncTask;

public class MyActivity extends Activity {

    private static final String TAG = "ASYNC_TASK";

    private Button excute;
    private Button cancle;
    //private ProgressBar progressBar;
    private TextView textView;

    private MyTask mTask;
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        excute = (Button)findViewById(R.id.execute);
        //excute.setOnClickListener(new View.OnClickListener(){
        excute.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v){
                //注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常
                //mTask = new MyTask();
                //mTask.execute("http://www.baidu.com");

                MyTask tmpTask = new MyTask();
                tmpTask.execute("nothing");

                excute.setEnabled(false);
                //cancel.setEnabled(true);
            }
        });

        textView = (TextView) findViewById(R.id.text_view);
    }

    private class MyTask extends AsyncTask<String,Integer,Integer> {
        @Override
        protected void onPreExecute(){
            Log.i(TAG,"OnPreExcute called");
            textView.setText("loading...");
        }

        @Override
        protected Integer doInBackground(String... param){
            Log.i(TAG, "doInBackground called");

            try{

                for (int i=0;i<3;++i) {
                    Thread.currentThread().sleep(2000);
                    publishProgress(i);
                }

            }catch (InterruptedException e){
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... progress){
            Integer i = progress[0];

            textView.setText("load progress" + i);

        }

        @Override
        protected void onPostExecute(Integer result) {
            textView.setText("load sucessful");
        }
    }
}

Java开发与c++开发有很大差异,在上述代码中我故意将task设置为局部变量,而程序仍然可以正常工作,可见ava对象不具备和基本类型一样的生命周期,在对象超出作用域后,系统并未对对象进行销毁
当你用new创建一个Java对象时,它可以存活于作用域之外。所以假如你有下面的代码:
{
String s = new String(‘a string’);
} // End of scope
引用s在作用域终点就消失了。然而,s指向的String对象仍继续占据内存空间。在这一小段代码中,我们似乎无法再访问这个对象,因为对它唯一的引用已超出了作用域的范围。
事实证明,由new创建的对象,只要你需要,就会一直保留下去。这样,许多C++编程问题在Java中就完全消失了。在C++中,最难的问题似乎在于:程序员并不能从语言本身中获得任何帮助,以确保在需要调用对象时,该对象仍可用。更重要的是:在C++中,一旦使用完对象后,你必须确保要销毁对象。
这样便带来一个有趣的问题。如果Java让对象继续存在,那么靠什么才能防止这些对象填满内存空间,进而阻塞你的程序呢?这正是C++里可能会发生的问题。则正是Java神奇之所在。Java有一个“ 垃圾回收器”,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其它新的对象使用。也就是说,你根本不必担心内存回收的问题。你只需要创建对象,一旦不再需要,它们就会自行消失。这样做就消除了这类编程问题:即所谓的“内存溢出”,即由于程序员忘记释放内存而产生的问题。
3、生命周期与AsyncTask
当由异步任务启动的进度对话框可见时,用户单击back按钮,会出现什么情况呢?按照Android的指导方针,这个操作会取消对话框。然而如果没有取消异步任务,那么它会继续执行,所以需要在捕捉对话框的oncacel事件,取消异步任务。
如果用户不使用进度对话框,而使用其它进度展示方式,又会出现什么情况?如果用户通过back或者home键离开activity,又会出现什么情况?在这两种情况下我们都无法确定用户何时返回,这个时候正确的做法是确认Activity的生命周期,然后相应的处理异步任务。
总之,异步任务需要充分意识到Activity的生命周期状态,并在何时的时机处理异步任务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值