Android之异步调用
概述
AsyncTask可以很好的,准确的使用UI线程,他可以将一个比较耗时(几秒钟)的动作运行在后台,并且能将结果返回至UI线程中,不需要通过(Thread操作和Handler操作)。
使用时必须通过创建一个AsyncTask的子类,至少重写其doInBackground(顾名思义,你想在后台执行怎样的一个操作)方法,大多数也会重写onPostExcute(后台执行完之后你想将一个结果返回在UI线程的哪里)方法。AsyncTask的三种泛型定义和四个步骤
首先了解AsyncTask的三种泛型定义,如图:
Params:执行后台操作时发给任务的参数类型,即doInBackground方法的参数,例:如果执行后台下载图片的文件,此处可为String 类型的imagePath。
Progress:后台操作执行过程中进度的类型。
Result:返回给UI线程的数据类型。即onPostExcute方法的参数,例:如果后台执行的是一个图片下载任务,此处肯定将返回一个Bitmap类型给UI线程。
当然并不是所有的类型都会使用到,例如Progress,如果不需要显示进度条,将无需设计这个类型,直接用Void类型。
其次了解其四个步骤:
onPreExcute:执行后台任务之前做的操作,例如可以是弹出一个Dialog提示用户正在下载中。同时需要在onPostExcute方法中将该Dialog dismiss。
onInBackground:略。前面已讲述。补充:此方法中可以使用publishProgress发布进度单元,且进度单元会发布在onProgressUpdate步骤中。
onProgressUpdate:顾名思义就是进行进度条的更新操作。将进度单元显示在UI线程中。
onPostExcute:略。补充:此方法的参数是doInBackground方法返回的结果。AsyncTask正常运行的条件:
①必须在UI线程中加载AsyncTask类。
②必须在UI线程中创建任务实例。
前面两点总结起来就是要在UI线程中创建AsyncTask的子类,并且必须在UI线程中实例化。
③在UI线程中调用excute()来执行任务。不要手动调用AsyncTask的四个步骤函数。为啥doInBackground方法中调用publishProgress,在onProgressUpdate可以实时更新进度条。
因为在调用publishProgress之前,doInBackground的任何记忆效应对onProgressUpdate来说是可见的,而且后续的publishProgress不会影响onProgressUpdate正在进行的操作。下面展示一个异步加载图片的操作
①准备工作
》访问网络图片,首先需要授予权限。Manifest.xml中节点之前添加如下语句开启APP访问网络的权限
》请求下载网络图片需要到HttpClient这个类,但是在Android 6.0之后不再支持HttpClient,但是还是可以用,需要在APP的build.gradle中添加如下代码:
②代码
package com.example.asynctask;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private Button btn;
private String imagePath="http://img.daimg.com/uploads/allimg/190504/3-1Z504145110.jpg";
private Bitmap bitmap;
private MyTask myTask;
private ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog=new ProgressDialog(this);
btn=(Button)findViewById(R.id.button);
imageView=findViewById(R.id.imageview);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置进度条为水平的
//progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myTask=new MyTask();//必须实例化
myTask.execute(imagePath);
}
});
}
//三个参数分别为图片下载路径,进度条标示值大小,位图
public class MyTask extends AsyncTask<String, Integer, Bitmap> {
//异步后台执行之前的操作,后台下载提醒框
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setTitle("温馨提示");
progressDialog.setMessage("请稍后,正在下载中");
progressDialog.show();
}
//后台执行操作
@Override
protected Bitmap doInBackground(final String... strings) {
HttpClient httpClient=new DefaultHttpClient();
HttpGet httpGet=new HttpGet(strings[0]);
try {
HttpResponse httpResponse=httpClient.execute(httpGet);
long file_len=httpResponse.getEntity().getContentLength();//图片总大小
int total_len=0;//当前的大小
int len=0;//一次读取的大小
byte[] data1=new byte[1024];
InputStream inputStream=null;
if(httpResponse.getStatusLine().getStatusCode()==200){
//将请求返回的实体转换为字节码
byte []data= EntityUtils.toByteArray(httpResponse.getEntity());
//将字节码转为位图
bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
inputStream=new ByteArrayInputStream(data);//将字节码转为流来读取图片
while((len=inputStream.read(data1))!=-1){
total_len+=len;
int progress_value=(int)((total_len/(float)file_len)*100);
System.out.println(progress_value);//测试进度条变化
publishProgress(progress_value);//进度条更新
}
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
//进度条变化,与在doInBackground中执行publishProgress方法配合使用
@Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]);
super.onProgressUpdate(values);
}
//结果返回
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
imageView.setImageBitmap(bitmap);//将得到的位图加载到图片组件中
progressDialog.dismiss();//关闭进度条
}
}
}
Android之异步调用的更多相关文章
- Android Handler 异步调用修改界面与主线程
在Android编程的过程中,如果在Activity中某个操作会运行比较长的时间,比如:下载文件.这个时候如果在主线程中直接下载文件,会造成Activity卡死的现象:而且如果时间超过5秒,会有ANR ...
- ArcGIS Runtime for Android 使用异步GP服务绘制等值线
关于基于Android上ArcGIS Server GP服务的调用,已经有前辈给出了很好的例子: http://blog.csdn.net/esrichinacd/article/details/92 ...
- (转)ArcGIS Runtime for Android 使用异步GP服务绘制等值线
关于基于Android上ArcGIS Server GP服务的调用,已经有前辈给出了很好的例子: http://blog.csdn.net/esrichinacd/article/details/92 ...
- Android 图片异步加载的体会,SoftReference已经不再适用
在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>> 这样软引用的 ...
- Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- Android图片异步加载之Android-Universal-Image-Loader(转)
今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决 ...
- Android使用ksoap2调用C#中的webservice实现图像上传
目录: 一. android使用ksoap2调用webservice 二. 异步调用 三. Android使用ksoap2调用C#中的webservice实现图像上传参考方法 四. 图像传输中Base ...
- Android:异步处理之Handler、Looper、MessageQueue之间的恩怨(三)
前言 如果你在阅读本文之前,你不知道Handler在Android中为何物,我建议你先看看本系列的第一篇博文<Android:异步处理之Handler+Thread的应用(一)>:我们都知 ...
- Android:异步处理之AsyncTask的应用(二)
前言 在上一篇文章中<Android:异步处理之Handler+Thread的应用(一)>,我们知道Android的UI主线程主要负责处理用户的按键事件.用户的触屏事件以及屏幕绘图事件等: ...
随机推荐
- 神经网络训练技巧:训练参数初始化、Drop out及Batch Normalization
参数初始化: xavier初始化: https://blog.csdn.net/VictoriaW/article/details/73000632 条件:优秀的初始化应该使得各层的激活值和梯度的方差 ...
- “HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求”之解决办法
今天同事在做通过接口访问数据时,由于提交的一个参数内容比较多,导致测试时报了以下错误. 同时页面又给出了以下提示: 所以最终根据在网上找了相关资料总结出一下解决办法. 1. 在Web.config配置 ...
- iptables常用语法与案例
常用命令语法: [root@www ~]# iptables [-t tables] [-L] [-nv] 选项与参数: -t :后面接 table ,例如 nat 或 filter ,若省略此项目, ...
- BSOJ5458 [NOI2018模拟5]三角剖分Bsh 分治最短路
题意简述 给定一个正\(n\)边形及其三角剖分,每条边的长度为\(1\),给你\(q\)组询问,每次询问给定两个点\(x_i\)至\(y_i\)的最短距离. 做法 显然正多边形的三角剖分是一个平面图, ...
- py-R-FCN的caffe配置(转)
参考:https://blog.csdn.net/wei_guo_xd/article/details/74451443 下载程序,git clone https://github.com/Orpin ...
- [luogu]P2680 运输计划[二分答案][树上差分]
[luogu]P2680 [NOIP2015]运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n ...
- BFC、IFC、GFC和FFC
基本概念 Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个Box 组成的.元素的类型和 display 属性,决定了这个 Box 的类型. 不同类型的 Box, 会参与不 ...
- Linq in not in\like not like
别人的博客 http://blog.163.com/lesheng@126/blog/static/357364652010102111051668/ using System.Data.Linq.S ...
- echarts曲线图
drawLeftLine(){ let drawLine = echarts.init(document.getElementById('data-left-middle-table-wrap')); ...
- Spring Cloud架构教程 (五)服务网关(过滤器)
过滤器的作用 通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了.但是,每个客户端用户请求微服务应用提供的接口时,它们 ...