`
radio123
  • 浏览: 205279 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

【转】 android 异步处理AsynTask实例讲解

 
阅读更多

http://tech.it168.com/a2012/0312/1323/000001323193.shtml


    android提供了一套专门用于异步处理的类。即:AynsTask类。使用这个类可以为耗时程序开辟一个新线程进行处理,处理完时返回。
  其实,AsynTask类就是对Thread类的一个封装,并且加入了一些新的方法。编程时,两者都可以实现同样的功能。本文后面将对AsynTask和Thread进行比较。

1、AsynTask类结构
  asysTask类主要用到的几个内部回调函数有:
doInBackGround()
onPreExecute()
onPostExecute()
onProgressUpdate()
正是这几个回调函数构成了AsynTask类的使用逻辑结构。
  注意:每个AsynTask子类必须至少要重写doInBackGround()方法。
2、回调逻辑关系
  1>主线程调用AsynTask子类实例的execute()方法后,首先会调用onPreExecute()方法。onPreExecute()在主线程中运行,可以用来写一些开始提示代码。
  2>之后启动新线程,调用doInBackground()方法,进行异步数据处理。
  3>处理完毕之后异步线程结束,在主线程中调用onPostExecute()方法。onPostExecute()可以进行一些结束提示处理。
  补充:在doInBackground()方法异步处理的时候,如果希望通知主线程一些数据(如:处理进度)。这时,可以调用publishProgress()方法。这时,主线程会调用AsynTask子类的onProgressUpdate()方法进行处理。
3、各个函数间数据的传递
  通过上面的调用关系,我们就可以大概看出一些数据传递关系。如下:
execute()向doInBackground()传递。
doInBackground()的返回值会传递给onPostExecute()
publishProgress()progressUpdate()传递。
要点:为了调用关系明确及安全,AsynTask类在继承时要传入3个泛型。
第一个泛型对应execute()向doInBackground()的传递类型。
第二个泛型对应doInBackground()的返回类型和传递给onPostExecute()的类型。
第三个泛型对应publishProgress()向progressUpdate()传递的类型。

  传递的数据都是对应类型的数组,数组都是可变长的哦。可以根据具体情况使用。
点击按钮,执行异步操作,执行过程中不断刷新显示内容。
开始界面只有一个按钮.点击按钮后,效果如下:
[Android]异步处理AsynTask实例讲解

可以看到Progress后面的数字不停改变:
[Android]异步处理AsynTask实例讲解

一直到变为100为止。变为100后,界面如下:
[Android]异步处理AsynTask实例讲解

 
 
首先写一个类用来记录线程信息。方便我们跟踪调试。
package com.example.helloAndroid;
import android.util.Log;

public class LogUtils {
    private static final String TAG = "LogUtils";
   
    public static final void thread()
    {
        LogUtils.thread(null);
    }
   
    public static final void thread(String msg){
        Thread t = Thread.currentThread();
        Log.d(TAG, "<" + t.getName() + ">id: " + t.getId() + ", Priority: " + t.getPriority() + ", Group: " + t.getThreadGroup().getName()
                + (msg != null? ",Msg:" + msg : ""));
    }
}
 接着我们新建一个layout的xml文件。内容如下:
 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/widget33"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">
<Button android:id="@+id/btnNotify"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start" />
<TextView
    android:id="@+id/txt1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="" />        
</LinearLayout>
现在我们建一个类用来异步处理数据:
package com.example.helloAndroid;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.TextView;

public class Calculator extends AsyncTask<List<Integer>, Integer, Integer> {

    private static final String TAG = "Calculator";
    private Context context;
    private TextView txt1;
    private Integer nResult;
    private Integer nProgress;
   
    public Calculator(Context context)
    {
        this.setContext(context);
    }
   
    public void setContext(Context context)
    {
        this.context = context;
        this.txt1 = (TextView)((Activity)this.context).findViewById(R.id.txt1);
        this.progressUI();
    }
   
    //在处理完毕后,修改界面。只修改了一次界面。
    public void syncUI(){
        //用来看调试信息
        LogUtils.thread("update ui...");
        //修改界面显示内容
        this.txt1.setText("calculate ..." + this.nResult);
    }
   
    @Override
    protected Integer doInBackground(List<Integer>... params)
    {
        //用来看调试信息
        LogUtils.thread("execute calculating...");
       
        this.nResult = 0;
        Integer p;
        for(int i=0; i<params[0].size(); i++)
        {
            p = params[0].get(i); //p为数字1,2,3,...10
            this.nResult += p.intValue(); //nResult = 1+2+3+...10
            LogUtils.thread("calculating..." + this.nResult);
            //update progress
            this.publishProgress(100 * (i+1)/params[0].size());
            try
            {
                Thread.sleep(1000);
            }
            catch(InterruptedException e)
            {}
        }
        LogUtils.thread("completed calculator..." + this.nResult);
        return this.nResult;
    }
   
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        LogUtils.thread("before calculating...");
        // 在 Main Thread 裡執行,可更新 UI
        this.nProgress = 0;
    }
   
    @Override
    protected void onPostExecute(Integer result)
    {
        super.onPostExecute(result);
        this.nResult = result;
        LogUtils.thread("calcuted result..." + this.nResult);
        // 在 Main Thread 裡執行,可更新 UI
        this.syncUI();
    }
   
    @Override
    protected void onProgressUpdate(Integer...values)
    {
        super.onProgressUpdate(values);
        this.nProgress = values[0];
        LogUtils.thread("Progress..." + this.nProgress);
        // 在 Main Thread 裡執行,可更新 UI
        this.progressUI();
    }
   
    //在处理过程中,数字不断改变。即不断刷新界面
    private void progressUI()
    {
        //用来看调试信息
        LogUtils.thread("Update Progress...");
        //修改界面显示内容
        this.txt1.setText("Progress:" + this.nProgress);
    }
}
 
然后就是最直观的界面操作了。新建一个Activity。
public class TestActivity extends Activity {
    private Calculator task;
    private String TAG = "AsyncTask";
   
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.d(TAG, "onCreate");
        // 重新連線
        this.task = (Calculator)this.getLastNonConfigurationInstance();
        if(this.task != null)
        {
            Log.d(TAG, "reconnect with asyncTask");
            this.task.setContext(this);
            // 在 Activity 重起過程中已計算完畢,所以要呼叫 AsyncTask 來更新 UI
            if(this.task.getStatus() == AsyncTask.Status.FINISHED)
            {
                this.task.syncUI();
            }
        }
        else
            Log.d(TAG, "task is null");
       
        findViewById(R.id.btnTest).setOnClickListener(calculatorClick);
}
   
    @Override
    public Object onRetainNonConfigurationInstance(){
       // 保留 Activity 與 AsyncTask 的關聯
        // 供 Activity 因故重起後,可以找回已在執行的 AsyncTask
        return this.task;
    }
   
    private View.OnClickListener calculatorClick = new View.OnClickListener() {
        public void onClick(View v) {
            // TODO Auto-generated method stub
            executeTask();
        }
    };
   
    public void executeTask() {
        Log.d(TAG, "Clicked");
        if(task != null)
        {
            AsyncTask.Status status = task.getStatus();
            Log.d(TAG, "Now status: " + status);
            if(status != AsyncTask.Status.FINISHED)
            {
              //前一計算未完成,不可重起計算
                Log.d(TAG, "continue last calculating ...");
                return;
            }
            //前一計算已完成,可重起計算
            Log.d(TAG, "completed last calculator");
        }
        Log.d(TAG, "new calculator");
        task = new Calculator(this);
        List<Integer> params = new ArrayList<Integer>();
        for(int i=0; i<10; i++)
            params.add(i);
        // 只能呼叫一次 execute(...)
        task.execute(params);
    }
}
 
执行后效果如下:
 [Android]异步处理AsynTask实例讲解
5、总结
  初次看到这个异步调用关系可能觉得很复杂,但其实熟悉了之后会发现这种结构很好用。这种结构将所有的线程通信都封装成回调函数,调用逻辑容易书写。
    尤其是在异步处理结束之后,有回调函数进行收尾处理。
    如果是使用Thread的run()方法,run()结束之后没有返回值。所以必须要自己建立通信机制。
    但是,其实使用Handler+Thread机制其实完全可以替代AsynTask的这种调用机制。只要将Handler对象传给Thread,就可以进行方便的异步处理。且这种MVC模式结构更加明显,方便管理。所以我觉得,使用asynTask还是Handler+Thread结构,个人喜好吧。
 
实际应用可以参考这篇博文:用AsyncTask从服务器下载文件并显示进
分享到:
评论

相关推荐

    android异步下载图片实例/解析xml实例

    这个实例结合了Android的异步处理、XML解析和网络请求技术,展示了如何从豆瓣电影API获取数据并展示给用户。对于Android初学者,这是一个很好的学习项目,涵盖了实际开发中的关键技能。同时,使用Picasso或Glide来...

    android asynTask 异步后台线程 各种操作

    在Android开发中,异步处理是非常重要的一环,特别是在UI线程中执行耗时操作时。`AsyncTask`是Android提供的一种轻量级的异步处理机制,它可以帮助开发者在后台线程执行任务,然后在主线程更新UI,避免了因长时间...

    Android异步加载文字

    总之,“Android异步加载文字”项目涵盖了Android应用开发中的基本异步处理技巧,通过学习和实践,开发者可以掌握如何在后台加载数据并安全地更新UI,提高应用的性能和用户体验。同时,这也是Android应用开发进阶...

    Android核心技术与实例讲解(源码)

    在Android开发领域,掌握核心技术与实例讲解至关重要,因为它们构成了开发者构建高效、稳定且用户体验优秀的应用的基础。这个压缩包中的"Android核心技术与实例讲解(源码)"无疑为学习和实践Android编程提供了宝贵的...

    Android异步任务AsyncTask实例源码

    Android是单线程模型,耗时的操作必须放在非主线程中执行,对此,我们需要使用多线程/线程池或者AsyncTask等来完成异步加载任务。 博客地址:http://blog.csdn.net/chenzheng8975/article/details/53893666

    Android异步加载图片例子

    在Android开发中,异步加载图片是一项至关重要的技术,尤其对于那些包含大量图像的移动应用而言,如社交网络、电商应用等。异步加载能够提高用户体验,避免UI线程阻塞,防止应用出现"卡死"现象。在这个"Android异步...

    android异步操作实例

    本实例聚焦于`AsyncTask`,它是Android提供的一种轻量级异步处理机制,特别适合于进行UI线程与后台线程之间的数据交互。 `AsyncTask`类有三个泛型参数:`Params`、`Progress`和`Result`。`Params`表示后台任务的...

    android 异步显示View

    在Android开发中,异步加载View是一个常见的需求,特别是在处理大量数据或者网络请求时,为了保证用户界面的流畅性,我们需要将耗时的操作放在后台执行,然后在主线程更新UI。这篇博客“android 异步显示View”可能...

    android核心技术与实例讲解源码

    本资料集合了"android核心技术与实例讲解源码",旨在帮助开发者深入理解Android系统的工作原理,并通过实践案例提升编程能力。以下是对这些核心知识点的详细阐述: 1. **Android架构**:Android系统基于Linux内核,...

    Android核心技术与实例讲解.pdf

    《Android核心技术与实例讲解》是一本深入探讨Android开发技术的书籍,主要涵盖了Android系统的各个方面,旨在帮助开发者理解和掌握Android开发的核心概念与实践技巧。通过本书,你可以了解到Android应用开发的基础...

    android异步加载网络图片实例

    Android 提供了 `AsyncTask` 类来执行后台操作,它非常适合处理轻量级的异步任务,如加载小尺寸的网络图片。`AsyncTask` 包含三个泛型参数,分别代表输入类型、进度类型和输出类型。在 `doInBackground()` 方法中...

    android异步加载图片实例

    android图片的异步加载,主要原理: 加载图片时先查看缓存中时候存在该图片,如果存在则返回该图片,否则先加载载一个默认的占位图片,同时创建一个通过网络获取图片的任务并添加,任务完成后放松消息给主线程更新...

    Android Studio实例代码.zip_Android app实例_Android实例_android app源码_and

    本压缩包“Android Studio实例代码.zip”包含了多个Android app的实例源码,旨在帮助开发者深入理解并实践Android应用开发。 1. **Android Studio基础** Android Studio基于IntelliJ IDEA,提供了强大的代码编辑、...

    android核心技术与实例详解16-18章PPT

    在Android开发领域,掌握核心技术与实例应用是提升开发能力的关键。本资料集合了"android核心技术与实例详解16-18章PPT"的内容,涵盖了Android系统中的重要知识点,旨在帮助开发者深入理解并熟练运用这些技术。以下...

    Android异步下载网络图片 (三个全)

    Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 ...

    android核心技术与实例详解光盘源代码3

    在本资源中,我们聚焦于Android开发的核心技术和实例解析,主要涵盖了光盘源代码的第13至第18章。这些章节深入探讨了Android应用开发的关键方面,为开发者提供了丰富的学习材料。以下是对各章节内容的详细解读: 第...

    Android AsyncTask异步处理下载网页

    在Android应用开发中,异步处理是至关重要的,特别是在涉及到耗时操作如网络请求、数据库操作或文件I/O时。Android提供了一种便捷的机制,名为`AsyncTask`,用于在后台线程执行这些任务,同时允许在主线程更新UI。`...

    Android异步处理二:使用AsyncTask异步更新UI界面

    Android异步处理二:使用AsyncTask异步更新UI界面。

    android 异步操作框架

    Android提供了多种异步处理框架,其中一个被广泛使用的开源框架是“android-async-http”,它是一个轻量级、高性能的网络库,非常适合进行HTTP请求。 **Android异步操作的重要性** 在Android系统中,主线程负责处理...

    android中异步消息处理

    ### Android中异步消息处理详解 #### 一、引言 在Android开发中,了解如何高效地处理异步消息是至关重要的。这不仅涉及到应用程序的响应性和用户体验,还关系到程序逻辑的正确实现。本篇文章将详细介绍Android中的...

Global site tag (gtag.js) - Google Analytics