AsyncTask的使用

由于AsyncTask是一个抽象类,所以我们想使用它,就必须创建一个子类去继承它。

在继承时我们可以为AsyncTask指定3个泛型参数:

params:在执行AsyncTask时需要传入的参数,用于在后台任务中使用;

progress:后台任务执行时,如果需要对结果进行返回,则使用这里指定的泛型作为返回值;

result:当后台任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型;

这是我定义的一个AsyncTask子类

private class DownloadTask extends AsyncTask<String,Object,Long>{}

在DownloadTask子类里,我继承了AsyncTask,把第一个泛型参数指定为String,表示在执行时要使用的数据,第二个参数指定为Object,表示在返回数据时的类型,第三个指定为Long,表示使用Long数据来反馈执行结果;

这时我们定义的AsyncTask还只是个空任务,需要重写几个方法才能完成对任务的制定。经常需要重写的方法有以下四个:

1.onpreExecute()

这个方法会在后台任务执行前调用,用于进行一些界面上的初始化操作,这个方法也是在主线程中调用的

这是我定义的onpreExecute()

        @Override
        protected void onPreExecute() {
            Log.i("iSpring", "MainActivity - > oncreate , Thread name: " +  Thread.currentThread().getName());
            super.onPreExecute();
            btn_start.setEnabled(false);
            textView.setText("开始下载....");
        }

初始化程序界面,一个Button值设为不可点击和TextView显示开始下载

2.doInBackGround(params...)

这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有耗时任务。任务一旦完成就可以通过return语句来将任务结果执行返回,在方法里我们是不可进行UI更新的,可以调用publishprogress()方法来完成反馈任务执行进度;

这是我定义的doInBackGround

 @Override
        protected Long doInBackground(String... strings) {
            Log.i("iSpring", "MainActivity - > oncreate , Thread name: " +  Thread.currentThread().getName());
            long totalByte = 0;
            for(String url: strings){
                Object[] result= downloadSingleFile(url);
                int byteCount = (int) result[0];
                totalByte += byteCount;
                publishProgress(result);
                if(isCancelled()){
                    break;
                }
            }
            return totalByte;
        }

在方法里,我传入了一个String[]数组泛型参数用于调用任务使用,用一个for()遍历取出String进行任务操作,for循环里调用了一个自己定义的downloadsing

private Object[] downloadSingleFile(String str){

            Object[] result = new Object[2];
            int byteCount = 0;
            String blogName = "";
            HttpURLConnection conn = null;
            try{
                URL url = new URL(str);
                conn = (HttpURLConnection)url.openConnection();
                InputStream is = conn.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buf = new byte[1024];
                int length = -1;
                while ((length = is.read(buf)) != -1) {
                    baos.write(buf, 0, length);
                    byteCount += length;
                }
                String respone = new String(baos.toByteArray(), "utf-8");
                int startIndex = respone.indexOf("<title>");
                if(startIndex > 0){
                    startIndex += 7;
                    int endIndex = respone.indexOf("</title>");
                    if(endIndex > startIndex){
                        //解析出博客中的标题
                        blogName = respone.substring(startIndex, endIndex);
                    }
                }
            }catch(MalformedURLException e){
                e.printStackTrace();
            }catch(IOException e){
                e.printStackTrace();
            }finally {
                if(conn != null){
                    conn.disconnect();
                }
            }
            result[0] = byteCount;
            result[1] = blogName;
            return result;
        }

3.onProgressUpdate(progress...)

这个方法会在后台任务调用publishProgress(Progress...)方法后调用,接收一个指定的泛型参数,参数用于更新UI操作

@Override
        protected void onProgressUpdate(Object... values) {
            Log.i("iSpring", "MainActivity - > oncreate , Thread name: " +  Thread.currentThread().getName());
            super.onProgressUpdate(values);
            int byteCound = (int) values[0];
            String blogName = (String) values[1];
            String text = textView.getText().toString();
            text += "\n博客《"+blogName+"》下载完成,共"+byteCound+"字节;";
            textView.setText(text);
        }

在我重写的onProgressUpdate()里接收一个Object[]数组,取出数组里的值进行更新UI

4.onPostExecute(Result)

这个方法会在后台任务执行完毕后并通过return返回时被调用。返回的数据会作为参数被传递到该方法中.

        @Override
        protected void onPostExecute(Long aLong) {
            Log.i("iSpring", "MainActivity - > oncreate , Thread name: " +  Thread.currentThread().getName()+",Long值:"+aLong);
            super.onCancelled();
            btn_start.setText("下载完成");
            btn_start.setEnabled(true);
        }

一个比较完整的自定义AsyncTask就完成了

可以在Main中实例化,并调用execute()方法执行任务了;

   
    @Override
    public void onClick(View view) {
        String[] urls = {
                "https://www.jianshu.com/p/17bb465173a6",
                "https://www.jianshu.com/p/f03a3dc55941",
                "https://www.jianshu.com/p/f9e8de453583",
                "https://www.jianshu.com/p/e1ea9e542112",
                "https://www.jianshu.com/p/0d36cefdb1a5"};

        DownloadTask task = new DownloadTask();
        task.execute(urls);
    }

在onClick()方法中初始化一个String[]数组作为参数在execute()中传入

简单来说,使用AsyncTask的诀窍就是,在doInbackGround()中执行具体的耗时操作,在onProgressUpdate()中进行UI更新,在onPostExecute()中执行任务收尾工作。

ps:在使用HttpURLConnection时会用到网络权限,别忘记在清单文件中添加权限

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

效果:



猜你喜欢

转载自blog.csdn.net/m0_37176478/article/details/80016796