异步任务AsyncTask
来源:互联网 发布:知肤泉水光面膜怎么用 编辑:程序博客网 时间:2024/05/16 10:31
为什么需要异步任务?
1.Android单线程模式,意思是只有主线程(UI线程)才能对UI进行更新操作,而其他的线程是不能操作UI。这样就保证饿了一个UI的稳定性,和准确性。
2.耗时操作放在非主线程中进行操作
AsyncTask为什么会有?
1.可以在子线程中进行UI的更新。
2.封装,简化了异步操作
构建AsyncTask子类的参数
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承,其中的三个泛型参数分别代表:
Params:启动任务时输入的参数类型
Progress:后台任务执行中返回进度值的类型
Resule:后台执行任务完成后返回的结果类型
构建AsyncTask子类的回调方法
doInBackground:必须重写,异步执行后台线程将要完成的任务。所有耗时的操作都在这里执行
onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化的操作就在这里执行
onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法中的返回值传递给该方法
onProgressUpdate:在doInBackground()方法中调用publicProgress()方法更新任务的执行进度后,会触发该方法。我们通过这个方法可以很清楚的知道当前耗时操作的一个完成进度。
简单实现,了解AsyncTask的执行
1.我们需要新建一个MyAsyncTask:
2.然后到MainActivity中进行启动:package com.example.songz.asynctasktest;import android.os.AsyncTask;import android.util.Log;/** * Created by SongZ on 2016/4/10. */public class MyAsyncTask extends AsyncTask<Void,Void,Void> {@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values); Log.d("szx","onProgressUpdate"); }@Overrideprotected void onPreExecute() {super.onPreExecute(); Log.d("szx","onPreExecute"); }@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid); Log.d("szx","onPostExecute"); }@Overrideprotected Void doInBackground(Void... params) { Log.d("szx","doInBackground"); publishProgress();return null; }}
3.结果显示:MyAsyncTask task = new MyAsyncTask();task.execute();
创建UI
异步处理-->下载图像
UI线程-->设置图像
1.首先我们新建一个布局名字叫做image:
2.然后新建一个class名字叫做ImageTest:<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:padding="16dp"android:layout_height="match_parent"> <ImageViewandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="match_parent"/> <ProgressBarandroid:visibility="gone"android:id="@+id/progressbar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"/></RelativeLayout>
创建AsyncTaskpublic class ImageTest extends Activity {private ImageView imageView;private ProgressBar progressBar;private static String URL="http://img.my.csdn.net/uploads/201504/12/1428806103_9476.png";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.image);imageView = (ImageView) findViewById(R.id.image);progressBar = (ProgressBar) findViewById(R.id.progressbar); }}
在上面的ImageTest代码中添加
class MySyncTask extends AsyncTask<String,Void,Bitmap>{//1.URL类型,2.进度值类型 3.返回值类型@Overrideprotected void onPreExecute() {super.onPreExecute(); }@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap); }@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values); }@Overrideprotected Bitmap doInBackground(String... params) { String url =params[0];//doInBackground它传递进来的是一个可变长数组,也就是说在execute方法中可以传递不止一个参数进来,那么这些参数以此对应的就是我们params这个数组,因为我们传进来的参数只有一个,所以就是第0个,就可以取出对应的URLBitmap bitmap = null; URLConnection connection;//定义网络连接对象InputStream is;//用于获取数据的输入流try {//将url解析成bitmapconnection =new URL(url).openConnection();//获取网络连接对象is =connection.getInputStream();//获取输入流BufferedInputStream bis = new BufferedInputStream(is); bitmap = BitmapFactory.decodeStream(bis);//将输入流解析成bitmapis.close();//先打开的后关闭bis.close(); } catch (IOException e) { e.printStackTrace(); }return bitmap; }}
2.总结逻辑:
1.获取传递进来的参数,也就是params[0];
2.通过decodeStream解析输入流
3.将bitmap作为返回值返回给后面调用的方法
与UI线程通信
1.在上面代码中添加
2.然后设置传递进去的参数@Overrideprotected void onPreExecute() {super.onPreExecute();//这时候吧隐藏的progressbar显示出来,提示用户等待progressBar.setVisibility(View.VISIBLE);}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);//操作UI,设置图像progressBar.setVisibility(View.GONE);imageView.setImageBitmap(bitmap);}
3.然后在activity_main.xml中添加按钮点击事件//设置传递进去的参数new MySyncTask().execute(URL);
4.然后再到MainActivity中进行事件的实现<Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="Hello World!"android:onClick="loadImage"/>
模拟进度条protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyAsyncTask task = new MyAsyncTask(); task.execute();}public void loadImage(View view){ startActivity(new Intent(this,ImageTest.class));}
通过AsyncTask来模拟进度条的更新
1.首先还是需要新建一个类,叫做ProgressBarTest
2.然后还需要设计一个布局,里面的ProgressBar需要是水平方向的。package com.example.songz.asynctasktest;import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import android.widget.ProgressBar;/** * Created by SongZ on 2016/4/10. */public class ProgressBarTest extends Activity {private ProgressBar progressBar;private MyAsyncTask1 myAsyncTask;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.progressbar);progressBar = (ProgressBar) findViewById(R.id.pg);myAsyncTask = new MyAsyncTask1();myAsyncTask.execute(); }class MyAsyncTask1 extends AsyncTask<Void,Integer, Void>{@Overrideprotected void onPreExecute() {super.onPreExecute(); }@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid); }@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);//获取进度更新值progressBar.setProgress(values[0]); }@Overrideprotected Void doInBackground(Void... params) {//模拟进度更新for (int i = 0;i<100;i++) { publishProgress(i);try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } }return null; } }}
3. 然后需要到AndroidManifest,xml文件中进行注册,然后再到MainActivity.java中进行一个点击事件的实现<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:padding="16dp"android:layout_height="match_parent"> <ProgressBarstyle="?android:attr/progressBarStyleHorizontal"android:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/pg"android:layout_centerVertical="true"android:layout_centerHorizontal="true" /></RelativeLayout>
public void loadProgressBaar(View view){ startActivity(new Intent(this,ProgressBarTest.class));}
但是这里你会发现,如果我们每一次进入都需要等待上一个进度条完成之后才可以,这是为什么?因为AsyncTask的底层是通过线程池来进行实现的,如果一个线程没有执行完毕,那么后面的线程是没有办法进行的,必须要等到上一个线程执行完毕才可以执行。那么需要怎么实现呢?很简单,我们知道Activity的生命周期,那么让AsyncTask和他保持一致就可以了。
protected void onPause() {super.onPause();if (myAsyncTask!=null && myAsyncTask.getStatus() == AsyncTask.Status.RUNNING)//不为空,而且Running{//cancel方法只是将对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行myAsyncTask.cancel(true);//然后这里并没有将线程停止掉}}protected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);if (isCancelled()) {return; }//获取进度更新值progressBar.setProgress(values[0]);}//只有doInBackground才是运行在其他线程protected Void doInBackground(Void... params) {//模拟进度更新for (int i = 0;i<100;i++) {if (isCancelled()) {break; } publishProgress(i);try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } }return null;}
1 0
- Android异步任务AsyncTask
- AsyncTask异步任务
- 异步任务AsyncTask
- AsyncTask异步任务
- AsyncTask异步任务
- Android--AsyncTask异步任务
- Android AsyncTask异步任务
- 异步任务(AsyncTask)
- Android 异步任务 AsyncTask
- 异步任务(AsyncTask)
- android 异步任务 AsyncTask
- Android AsyncTask 异步任务
- Android AsyncTask异步任务
- AsyncTask异步任务
- AsyncTask异步任务
- AsyncTask异步任务
- 异步任务AsyncTask
- 异步任务AsyncTask
- js 滑窗
- Mac安装Cocoapods
- Metal 着色语言编程指南 八
- MFC中OnDraw与OnPaint的区别
- Http协议分析
- 异步任务AsyncTask
- [网络诈骗]BEC(Business Email Compromise 企业邮件受骇)
- ZOJ 3593 One Person Game 【带简单处理的扩展欧几里得】
- iOS设置图片最大尺寸
- 伪静态与静态
- 聊聊Socket、TCP/IP、HTTP、FTP及网络编程
- 使用指针ptr指针访问像素,并且减少颜色数量
- 查找之三:二叉排序树(续)
- Android基础控件 - ImageView