Android线程机制——AsyncTask
对于Android为什么要使用多线程,因为从Android4.0之后,谷歌规定了网络操作不允许放在主线程中执行,由此就有了多线程的机制,有个JAVA学习经验的朋友一定知道多线程指的是什么,简单来讲就是,在JAVA程序中,main()函数开启的即为这个程序的主线程,而我们为了完成一些耗时操作又不想影响到主线程的执行,这是我们往往通过Thread对象创建一个子线程来执行。简单的说,一个程序只有一个主线程,可以有多个主线程。在Android世界中也是这样,Android属于单线程模型,耗时操作必须放在非主线程中执行,故而谷歌为了方便我们使用线程,为我们提供一个AsyncTask多线程操作对象。
对于Android使用线程还有一点需要特别注意,哪就是Android不允许在子线程中更新UI,相信很多初学者一定遇到过这个问题,这个怎么解决呢?在Activity中,我们可以通过
new Thread(new Runnable() { @Override
public void run() {
Log.v("abc", "子线程执行");
runOnUiThread(new Runnable() { @Override
public void run() {
Log.v("abc", "返回主线程执行");
}
});
}
}).start();
来实现我们的效果,不过有一点需要注意的是,在Fragement中,runOnUiThread()不能使用,所以大家在使用时稍微注意一下即可。当然了Android中我们还可以通过Handler+Messager来完成多线程操作,对于这里个的使用,在之前的博客中已经为大家介绍,就不在赘述,下面我们开始介绍本篇的重点:AsyncTask的使用。
AsyncTask<Parans, Progress, Result>是一个抽象类,我们需要首先实现这个抽象类,然后才能使用,对于它的三个参数:Parans:启动任务时输入的参数类型;progress:后台任务执行中返回值的类型;Result:后台执行任务完成后返回的结果类型。
构建AsyncTask子类的回调方法:1、doInBackground:必须重写,异步执行后台线程将要完成的任务; 2、onPreExecute:执行后台耗时操作前被调用,通过用户完成一些初始化操作;3、onPostExecute:当doInBackground()完成之后,系统会自动调用,并将doInBackground()执行后的返回值,传递给onPostExecute()方法,简单来说就是,doInBackground()完成耗时操作,结果交个onPostExecute()方法更新UI;4、onProgressUpdate:在doInBackground()方法中,调用publishProgress()方法,更新任务的执行进度后,就会触发该方法。
说了这么多,相信你心中还有一定的疑惑,下面我们通过两个简单的Android小程序,为大家具体介绍一下AsyncTask的使用方法:
a、AsyncTask中是个抽象方法的执行顺序:
1、创建一个AsyncTask子类对象:
public class MyAsyncTask extends AsyncTask<Void, Void, Void> { @Override
protected void onPreExecute() {
super.onPreExecute();
Log.v("abc", "onPreExecute");
} @Override
protected Void doInBackground(Void... arg0) {
Log.v("abc", "doInBackground");
publishProgress(arg0);
return null;
} @Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.v("abc", "onPostExecute");
} @Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
Log.v("abc", "onProgressUpdate");
} }
2、在MainActivity中调用给子线程,进行执行:
public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyAsyncTask().execute();//启动执行 }
3、执行后打印的log日志:
通过这个日志信息,是不是解决了你心中的疑惑,下面我们看一个使用AsyncTask加载网络图片的例子。
b、加载网络图片:
1、首先创建一个承载Activity布局文件的xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
tools:context=".MainActivity" > <ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true"
/> </RelativeLayout>
布局文件很简单,就是一个ImageView+ProgressBar,在加载ImageView是我们通过ProgressBar来提醒用户等待。
2、创建我们的Activity对象:
public class AsyncTaskImager extends Activity { private ProgressBar pb;
private ImageView image;
private static final String url = "https://www.baidu.com/img/bdlogo.png"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.imager);
init();
new ImageAsyncTask().execute(url);
} private void init() {
pb = (ProgressBar) findViewById(R.id.progressbar);
image = (ImageView) findViewById(R.id.img);
} class ImageAsyncTask extends AsyncTask<String, Void, Bitmap>{ @Override
protected void onPreExecute() {
super.onPreExecute();
pb.setVisibility(View.VISIBLE);
} @Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
URLConnection conn = null;
String url = params[0];
try {
conn = new URL(url).openConnection();
InputStream in = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(in);
bitmap = BitmapFactory.decodeStream(bis);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
} @Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
pb.setVisibility(View.GONE);
image.setImageBitmap(result);
}
} }
到这里我们的大功已经基本完成了,最后不要忘记在AndroidManifest.xml中进行一下声明。
3、添加网络操作权限:
<uses-permission android:name="android.permission.INTERNET"/>
因为我们需要使用到网络连接,所以我们需要在AndroidManifest.xml中添加一个网络访问权限。
4、最后配上一张运行结果:
到这里关于AsyncTask的介绍就可以画上一个句号了,大家有什么疑问,欢迎留言讨论。对于本人理解上的不足,欢迎批评指点。谢谢
Android线程机制——AsyncTask的更多相关文章
- Android线程管理之AsyncTask异步任务
前言: 前面几篇文章主要学习了线程以及线程池的创建与使用,今天来学习一下AsyncTask异步任务,学习下AsyncTask到底解决了什么问题?然而它有什么弊端?正所谓知己知彼百战百胜嘛! 线程管理相 ...
- Android - 消息机制与线程通信
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luosheng ...
- Android中使用Thread线程与AsyncTask异步任务的区别
最近和几个朋友交流Android开发中的网络下载问题时,谈到了用Thread开启下载线程时会产生的Bug,其实直接用子线程开启下载任务的确是很Low的做法,那么原因究竟如何,而比较高大上的做法是怎样? ...
- android线程 Handler Message Queue AsyncTask线程模型 线程交互 + 修改Button样式 示例 最终easy整合版
首先原谅我把文章的标题写的这么长.其实我还嫌弃它短了因为 写不下去了所以我就不写了.因为我实在不知道该怎么定义这篇文章的标题或许应该叫 "乱谈"比较合适. 这样可能还体现了 ...
- Android线程间异步通信机制源码分析
本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础 ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- Android线程管理之Thread使用总结
前言 最近在一直准备总结一下Android上的线程管理,今天先来总结一下Thread使用. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Executo ...
- Android线程管理之ExecutorService线程池
前言: 上篇学习了线程Thread的使用,今天来学习一下线程池ExecutorService. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Execu ...
- Android多线程机制和Handler的使用
参考教程:iMooc关于Handler,http://www.imooc.com/learn/267 参考资料:Google提供Android文档Communicating with the UI T ...
随机推荐
- Connecting sql server2008 through C#
本实例只在于将通过ASP.NET上的控件(如button.textbox等)结合C#中类的应用,将自己需要的数据存入当地的SQL SERVER数据库中 首先我们在项目中需要建立一个ASP.NET We ...
- ASP.Net MVC跳转,分为form的submit提交跳转和ajax跳转
1,用jquery ajax跳转的话,需要在前台用window.location("跳转网址")来跳转,在success后使用 2,用原声的form的submit来跳转,如下图 3 ...
- iOS网络基础知识
iOS网络基础知识 1.一次HTTP请求的完整过程 (1)浏览器或应用发起Http请求,请求包含Http请求Http(请求),地址(url),协议(Http1.1)请求为头部 (2)web服务器接收到 ...
- docker on centos
docker最好在centos7上安装,centos6.5上似乎麻烦不少 这里直接在centos7上安装,要提前装一下epel的repo yum install docker 安装就行 chkconf ...
- 升级ruby后再安装cocodPod
1.移除现有的Ruby $gem sources --remove https://rubygems.org/ 2.使用淘宝镜像 $gem sources -a https://ruby.taobao ...
- 一用钟情的VS插件系列总目录(值得收藏)
关于插件,大家的印象可能很多,比如开发者经常使用的Chrome浏览器的扩展程序,某个软件的一个扩展程序等等.我们使用插件的目的是为了提高我们的某些方面的工作效率或者让我们的软件源(Chrome浏览器等 ...
- 微软颜龄Windows Phone版开发小记
随着微软颜龄中文网cn.how-old.net的上线,她也顺势来到了3大移动平台. 用户在微软颜龄这一应用中选择一张包含若干人脸的照片,就可以通过云计算得到他们的性别和年龄. 今天我们就和大家分享一下 ...
- Java IO2:RandomAccessFile
RandomAccessFile RandomAccessFile类可以说是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法.RandomAccessFile类支持"随机访 ...
- 一个不陌生的JS效果-marquee,用css3来实现
关于marquee,就不多说了,可以戳这里. 毕竟他是一个很古老的元素,现在的标准里头也不推荐使用这个标签了.但平时一些项目中会经常碰到这样的效果,每次都是重新写一遍,麻烦! JS类实现marquee ...
- Unity3D使用经验总结 缺点篇
不论是从官方手册,还是各种第三方教程,几乎涉及到的,都是讲如何使用U3D,以及U3D的优点. 虽然我是用的一个让步语气,但请不要否认U3D的这些优点,它们的确存在. 但对于一个引擎的特性来说,优点与缺 ...