Android必学之AsyncTask,多线程AsyncTask,详细AsyncTask使用教程

AsyncTask,即异步任务,是Android给我们提供的一个处理异步任务的类.通过此类,可以实现UI线程和后台线程进行通讯,后台线程执行异步任务,并把结果返回给UI线程.

  • 为什么需要使用异步任务?

我们知道,Android中只有UI线程,也就是主线程才能进行对UI的更新操作,而其他线程是不能直接操作UI的.这样的好处是保证了UI的稳定性和准确性,避免多个线程同时对UI进行操作而造成UI的混乱.但Android是一个多线程的操作系统,我们总不能把所有的任务都放在主线程中进行实现,比如网络操作,文件读取等耗时操作,如果全部放到主线程去执行,就可能会造成后面任务的阻塞.Android会去检测这种阻塞,当阻塞时间太长的时候,就会抛出Application Not Responsed(ANR)错误.所以我们需要将这些耗时操作放在非主线程中去执行.这样既避免了Android的单线程模型,又避免了ANR.

  • AsyncTask为何而生?

提到异步任务,我们能想到用线程,线程池去实现.确实,Android给我们提供了主线程与其他线程通讯的机制.但同时,Android也给我们提供了一个封装好的组件--AsyncTask.利用AsyncTask,我们可以很方便的实现异步任务处理.AsyncTask可以在子线程中更新UI,也封装简化了异步操作.使用线程,线程池处理异步任务涉及到了线程的同步,管理等问题.而且当线程结束的时候还需要使用Handler去通知主线程来更新UI.而AsyncTask封装了这一切,使得我们可以很方便的在子线程中更新UI.

  • 构建AsyncTask子类的泛型参数

AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承.继承AsyncTask需要指定如下三个泛型参数:

Params:启动任务时输入的参数类型.

Progress:后台任务执行中返回进度值的类型.

Result:后台任务执行完成后返回结果的类型.

  • 构建AsyncTask子类的回调方法

AsyncTask主要有如下几个方法:

doInBackground:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.

onPreExecute:执行后台耗时操作前被调用,通常用于进行初始化操作.

onPostExecute:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法.通过此方法进行UI的更新.

onProgressUpdate:当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法.通过此方法我们可以知晓任务的完成进度.

下面通过代码演示一个典型的异步处理的实例--加载网络数据.网络操作作为一个不稳定的耗时操作,从4.0开始就被严禁放入主线程中.所以在显示一个json串时,我们需要在异步处理中下载这些数据,并在UI线程中设置.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

切记加网络权限<uses-permission android:name="android.permission.INTERNET" />

 

在MainActivity中实例化AsyncTask 传入接口参数 

import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    //拼接参数
     private int page = 1;
     //接口地址
    private String path ="http://www.xieast.com/api/news/news.php";
    //参数 page 默认值是1

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

        MyAsyncTask task = new MyAsyncTask();
        //执行异步任务 execute接收可变参
        //传参
        task.execute(path+"?page="+page);
    }

自定义内部类里面的写法: 

 //创建一个对象继承抽象类AsyncTask
    private class MyAsyncTask extends AsyncTask<String,Integer, String>{


        //重写方法运行在主线程 做一些准备工作

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Toast.makeText(MainActivity.this, "客官请耐心等待", Toast.LENGTH_SHORT).show();

        }

        //重写抽象方法  此方法运行后台(子线程)  直接操作耗时操作
        @Override
        protected String doInBackground(String... parmas) {
            //取出传过来的参数  默认第一个
            String uri = parmas[0];

            //创建URL 把接口路径包装成网络地址

            try {
               // URL url = new URL(path+"?page="+page);
                URL url = new URL(uri);
                //打开连接
               HttpURLConnection conn= (HttpURLConnection) url.openConnection();
                //请求方式
               conn.setRequestMethod("GET");
                //连接服务器延时
               conn.setConnectTimeout(5000);
                //读取延时
               conn.setReadTimeout(5000);
                //获取状态码
                int responseCode = conn.getResponseCode();
                //状态码比较==200 有网执行以下
                if (responseCode==200){
                    //获取服务器资源
                    InputStream inputStream = conn.getInputStream();
                    //创建字节输出流
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    //创建字节变量
                    byte[] buffer = new byte[1024];
                    int len = 0;
                    //循环读取
                    while ((len=inputStream.read(buffer))!=-1){
                    //写入
                        outputStream .write(buffer,0,len);
                    }
                    //发布进度
                    publishProgress(10,2);
                    //关流
                    inputStream.close();
                    outputStream .close();
                    //获取到的数据 传给onPostExcute
                    String json = bos.toString();
                     return json;
                }

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

            return null;
        }
        //此方法运行在主线程 更新进度 publishProgress();些方法调用之后才会走
        @Override
        protected void onProgressUpdate(Integer... values) {
            //super.onProgressUpdate(values);
            Log.i("xxx",values[0]+","+values[1]);

        }

        //此方法运行主线程 接收耗时操作的结果
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);

            Log.i("xxx",s);
            //解析 给适配器即可
            //导入gson依赖
            Gson gson = new Gson();
            //创建好Bean类 -- 利用gson解析
            JsonBean jsonBean = gson.fromJson(json, JsonBean.class);
            ArrayList<Data> data = jsonBean.getData();
            //适配器进行展示
            listView.setAdapter(new MyAdapter(getActivity(), data));

        }
    }

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值