AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

使用的优点:

l  简单,快捷

l  过程可控

使用的缺点:

l  在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

2 )Handler异步实现的原理和适用的优缺点


AsyncTask介绍 Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。 首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

AsyncTask定义了三种泛型类型 Params,Progress和Result。

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。
  • Progress 后台任务执行的百分比。
  • Result 后台执行任务最终返回的结果,比如String。

使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

  • 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只能被执行一次,否则多次调用时将会出现异常;

下面给出一个我写的小demo,仅供大家参考,运行结果如图:

Android Studio利用异步任务AsyncTask发送post请求获取json数据_第1张图片

Android Studio利用异步任务AsyncTask发送post请求获取json数据_第2张图片

Android Studio利用异步任务AsyncTask发送post请求获取json数据_第3张图片

首先是AysncTask类:

package ly.asynctasktest;import android.content.Context;import android.os.AsyncTask;import android.widget.TextView;import android.widget.Toast;/** * Created by kfbmac3 on 16/7/8. */    /*      AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法。注意继承时需要设定三个泛型Params,      Progress和Result的类型,如AsyncTask:     Params是指调用execute()方法时传入的参数类型和doInBackgound()的参数类型     Progress是指更新进度时传递的参数类型,即publishProgress()和onProgressUpdate()的参数类型     Result是指doInBackground()的返回值类型        doInBackgound() 这个方法是继承AsyncTask必须要实现的,运行于后台,耗时的操作可以在这里做        publishProgress() 更新进度,给onProgressUpdate()传递进度参数        onProgressUpdate() 在publishProgress()调用完被调用,更新进度     */public class UpdateTextTask extends AsyncTask {    private Context context;    private String url;    private String postValue;    private TextView text;    UpdateTextTask(Context context , String string , String postValue , TextView text) {        this.context = context;        this.url = string;        this.postValue = postValue;        this.text = text;    }    /**     * 运行在UI线程中,在调用doInBackground()之前执行     * 该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置     */    @Override    protected void onPreExecute() {        Toast.makeText(context,"开始执行",Toast.LENGTH_SHORT).show();    }    /**     * 后台运行的方法,可以运行非UI线程,可以执行耗时的方法     * 这里的Void参数对应AsyncTask中的第一个参数     * 这里的String返回值对应AsyncTask的第三个参数     * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改     * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作     */    @Override    protected String doInBackground(Void... params) {        int i=0;        while(i<10){            i++;            //publishProgress 更新进度,给onProgressUpdate()传递进度参数            publishProgress(i);            try {                Thread.sleep(1000);            } catch (InterruptedException e) {            }        }        String result = Common.postGetJson(url,postValue);        //第三个参数为String 所以此处return一个String类型的数据        return result;    }    /**     * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)     * 运行在ui线程中,在doInBackground()执行完毕后执行,传入的参数为doInBackground()返回的结果     */    @Override    protected void onPostExecute(String i) {        Toast.makeText(context,i,Toast.LENGTH_SHORT).show();        text.setText(i);    }    /**     * 在publishProgress()被调用以后执行,publishProgress()用于更新进度     * 这里的Intege参数对应AsyncTask中的第二个参数     * 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行     * onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作     */    @Override    protected void onProgressUpdate(Integer... values)    {        //第二个参数为Int        text.setText(""+values[0]);    }}

接下来是发送http请求的方法:

package ly.asynctasktest;import android.util.Log;import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.List;import java.util.Map;/** * Created by kfbmac3 on 16/5/20. */public class Common {    public static String postGetJson(String url, String content) {        try {            URL mUrl = new URL(url);            HttpURLConnection mHttpURLConnection = (HttpURLConnection) mUrl.openConnection();            //设置链接超时时间            mHttpURLConnection.setConnectTimeout(15000);            //设置读取超时时间            mHttpURLConnection.setReadTimeout(15000);            //设置请求参数            mHttpURLConnection.setRequestMethod("POST");            //添加Header            mHttpURLConnection.setRequestProperty("Connection", "Keep-Alive");            //接收输入流            mHttpURLConnection.setDoInput(true);            //传递参数时需要开启            mHttpURLConnection.setDoOutput(true);            //Post方式不能缓存,需手动设置为false            mHttpURLConnection.setUseCaches(false);            mHttpURLConnection.connect();            DataOutputStream dos = new DataOutputStream(mHttpURLConnection.getOutputStream());            String postContent = content;            dos.write(postContent.getBytes());            dos.flush();            // 执行完dos.close()后,POST请求结束            dos.close();            // 获取代码返回值            int respondCode = mHttpURLConnection.getResponseCode();            Log.d("respondCode","respondCode="+respondCode );            // 获取返回内容类型            String type = mHttpURLConnection.getContentType();            Log.d("type", "type="+type);            // 获取返回内容的字符编码            String encoding = mHttpURLConnection.getContentEncoding();            Log.d("encoding", "encoding="+encoding);            // 获取返回内容长度,单位字节            int length = mHttpURLConnection.getContentLength();            Log.d("length", "length=" + length);//            // 获取头信息的Key//            String key = mHttpURLConnection.getHeaderField(idx);//            Log.d("key", "key="+key);            // 获取完整的头信息Map            Map> map = mHttpURLConnection.getHeaderFields();            if (respondCode == 200) {                // 获取响应的输入流对象                InputStream is = mHttpURLConnection.getInputStream();                // 创建字节输出流对象                ByteArrayOutputStream message = new ByteArrayOutputStream();                // 定义读取的长度                int len = 0;                // 定义缓冲区                byte buffer[] = new byte[1024];                // 按照缓冲区的大小,循环读取                while ((len = is.read(buffer)) != -1) {                    // 根据读取的长度写入到os对象中                    message.write(buffer, 0, len);                }                // 释放资源                is.close();                message.close();                // 返回字符串                String msg = new String(message.toByteArray());                Log.d("Common", msg);                return msg;            }            return "fail";        }catch(Exception e){            return "error";        }    }}

MainActivity:

package ly.asynctasktest;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import java.net.URLEncoder;public class MainActivity extends AppCompatActivity {    private Button btn;    private TextView text;    private String url = "http://192.168.24.104:3000/users";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btn = (Button) findViewById(R.id.btn);        text = (TextView) findViewById(R.id.text);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Update();            }        });    }    private void Update(){        try{            String value = URLEncoder.encode("username", "UTF-8") + "=" +                    URLEncoder.encode("anwei", "UTF-8") + "&" +                    URLEncoder.encode("userfullname", "UTF-8") + "=" +                    URLEncoder.encode("安威", "UTF-8");            UpdateTextTask updatetext = new UpdateTextTask(this, url, value , text);            updatetext.execute();        }catch(Exception e){            text.setText("error");        }    }}

需要注意的问题依然是要在AndroidManifest.xml文件中添加网络权限:

    

文中的url是我用node.js写的一个简单后台,接收到post信息后在MongoDB中查找数据并返回,后台接收到的数据如图:


想试试的朋友可以自己搭建一个简单的后台,这里奉上我的AndroidStudio项目(不包含node.js后台)点击打开链接

如果有不足之处,欢迎大家指出!!!朋友们如果有高见,也欢迎您不吝指导!!!

更多相关文章

  1. Android中的Http通信(三)之get、post传递参数到服务器
  2. Android内存泄漏的轻松解决方法
  3. Android中播放声音的两种方法
  4. Android Activity之间跳转出现短暂黑屏的处理方法和intent.setFl
  5. 基于xml类型的压缩数据流的android获取天气的方法
  6. 最新android studio注意事项打不开等问题6种解决方法
  7. Android核心分析 --分析方法论探讨之设计意图
  8. 为android开放类增加自定义成员方法[转]
  9. Android安卓系统提示应用程序未安装的解决方法

随机推荐

  1. 观摩Android最高权力的Context通用性接口
  2. 安卓(Android)九宫格布局介绍
  3. android 异常 Unable to instantiate act
  4. android JNI库实现reboot,recovery
  5. Android 自定义时钟控件
  6. Android(安卓)NDK环境搭建和开发入门
  7. Android PopulWindow创建与定位
  8. textview中字显示不全用。。。代替
  9. 8.0 Launcher3 背景透明
  10. Android仿跟谁学app中的课程表