宝剑锋从磨砺出,梅花香自苦寒来。这篇文章主要讲述android AsyncTask使用相关的知识,希望能为你提供帮助。
/** * 作者:crazyandcoder * 联系: *QQ: 275137657 *email: [email protected] * 转载请注明出处!
*/
异步任务 AsyncTask使用
android中实现异步机制主要有Thread加Handler和AsyncTask,今天主要记录一下AsyncTask的学习过程。以备以后之需。
一、构建AsyncTask子类的參数
AsyncTask< Params,Progress,Result> 是一个抽象类。
通经常使用于被继承,继承AsyncTask须要指定例如以下三个泛型參数。
- Params: 启动任务时输入參数的类型。
- Progress:后台任务运行过程中进度之的类型。
- Result:
后台运行任务完毕后返回结果的类型。
二、实现AsyncTask须要重写的方法 当一个异步任务运行的时候一般须要实现一下4个方法:
- onPreExcute:一般是用户完毕一些UI的初始化操作。譬如载入进度条等。
- doInBackground(Params...):当调用完onPreExcute()后马上运行这种方法,主要是后台进行一些耗时的操作,在这方法中能够调用publishProgress(Progress...)来显示任务已经运行的进度。
- onProgressUpdate(Progress...):在doInBackground()方法中调用publicProgress方法会触发该方法的运行,用于UI组件显示任务实时运行的进度。
- onPostExcute():当后台任务完毕后会调用此方法,后台运行任务返回的结果作为參数传递给这种方法,显示更新在UI主线程中。
Threading rules There are a few threading rules that must be followed for this class to work properly:1、The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN. 2、The task instance must be created on the UI thread. 3、execute(Params...) must be invoked on the UI thread. 4、Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually. 5、The task can be executed only once (an exception will be thrown if a second execution is attempted.)
大概意思就是说:
- 必须在UI主线程中创建AsyncTask的实例。
- excute()方法必须在UI主线程中调用。
- 不须要手动调用onPreExcute、doInBackground、onProgressUpdate、onPostExcute四个方法。
- 一个AsyncTask实例仅仅能运行一个任务。
本次demo主要实现的是异步载入一张网络图片,并在载入过程中显示载入的进度百分比,主要涉及到一些IO操作以及网络请求等知识点。
文章图片
文章图片
文章图片
图1 图2 图3
图1显示的是功能。主要是点击button后进入载入网络图片页面;
图2显示的是载入网络图片过程中的进度百分比;
图3显示的是当载入进度百分比为100%时,显示要载入的网络图片。
以下我们来分析一下详细的实现代码:
主界面的布局就不贴了,主要就是一个button按钮,然后在MainActivity中实现页面跳转,我们主要来看看ImageTest.class 中是怎样实现载入网络图片的。
首先是xml布局,布局非常easy。一个ImageView组件显示网络图片,一个ProgressBar组件用于显示运行进度。一个TextView用于显示载入的进度百分比。总得布局用RelativeLayout实现。
< ?
xml version="1.0" encoding="utf-8"?
> < RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > < ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="match_parent" /> < ProgressBar android:id="@+id/progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:visibility="gone" /> < TextView android:id="@+id/mTextprogress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="15%" android:layout_centerInParent="true" android:textSize="13sp" /> < /RelativeLayout>
然后是ImageTest.class,在这里面主要是载入网络图片的主题代码。代码中凝视写的都一清二楚。直接上代码了。【android AsyncTask使用】
package com.example.asynctaskdemo; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.nfc.Tag; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; /** * 显示一张网络图片 * * @author crazyandcoder * @date [2015-8-9 下午4:11:27] */ public class ImageTest extends Activity { private String TAG = "ImageTest.class"; private ImageView mImageView; private ProgressBar mProgressBar; private TextView mTextProgress; private MyAsyncTaskShowImg mTask; private static String mImgUrl = "http://h.hiphotos.baidu.com/image/pic/item/9922720e0cf3d7ca14dcc750f71fbe096b63a9ea.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.image); initView(); mTask = new MyAsyncTaskShowImg(); mTask.execute(mImgUrl); } private void initView() { mTextProgress = (TextView) findViewById(R.id.mTextprogress); mImageView = (ImageView) findViewById(R.id.imageView1); mProgressBar = (ProgressBar) findViewById(R.id.progress); } class MyAsyncTaskShowImg extends AsyncTask< String, Integer, Bitmap> {/** * 初始化UI控件 * * @see android.os.AsyncTask#onPreExecute() */ @Override protected void onPreExecute() { super.onPreExecute(); mProgressBar.setVisibility(View.VISIBLE); mTextProgress.setText("0%"); }/** * 运行复杂的耗时任务 * * @param params * @return * @see android.os.AsyncTask#doInBackground(Params[]) */ @Override protected Bitmap doInBackground(String... params) {// 网络中图片的地址 String mImgUrl = params[0]; String mFileName = "temp_pic"; Log.d(TAG, "mImgUrlis " + mImgUrl); // 网络中图片终于将转化为bitmap类型返回给imageview显示 Bitmap mBitmap = null; // 获取数据的输入流 InputStream is = null; OutputStream out = null; HttpURLConnection connection; try {// 将网络图片地址以流的方式转化为bitmap类型 connection = (HttpURLConnection) new URL(mImgUrl).openConnection(); connection.setDoInput(true); connection.setDoOutput(false); // 设置链接超时时间 connection.setConnectTimeout(10 * 1000); is = connection.getInputStream(); out = openFileOutput(mFileName, MODE_PRIVATE); byte[] data = https://www.songbingjia.com/android/new byte[1024]; // 每次读到的长度 int seg = 0; // 总得数据大小 long totalSize = connection.getContentLength(); Log.d(TAG,"total size is " + totalSize); // 如今的进度 long current = 0; // while (!(mTask.isCancelled()) & & (seg = is.read(data)) != -1) { // 当前总的进度 current += seg; Log.d(TAG, "current size is " + current); // 下载百分比 int progress = (int) ((float) current / totalSize * 100); Log.d(TAG, "progress size is " + progress); // 通知更新进度 publishProgress(progress); out.write(data, 0, seg); }mBitmap = BitmapFactory.decodeFile(getFileStreamPath(mFileName).getAbsolutePath()); Log.d(TAG, "file is " + getFileStreamPath(mFileName).getAbsolutePath()); connection.disconnect(); is.close(); out.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }return mBitmap; }/** * 显示从网络中载入图片的进度 * * @param values * @see android.os.AsyncTask#onProgressUpdate(Progress[]) */ @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); mTextProgress.setText(values[0] + "%"); }/** * 将doInBackground中运行的结果返回给该方法,用于更新UI控件 * * @param result * @see android.os.AsyncTask#onPostExecute(java.lang.Object) */ @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); mProgressBar.setVisibility(View.GONE); mTextProgress.setVisibility(View.GONE); mImageView.setImageBitmap(result); Toast.makeText(ImageTest.this, "图片载入完毕.", Toast.LENGTH_LONG).show(); } } @Override protected void onPause() { super.onPause(); if (mTask != null & & mTask.getStatus() == AsyncTask.Status.RUNNING) { //cancel方法仅仅是将AsyncTask相应的状态标记为cancel状态,不是真的取消 mTask.cancel(true); } }}
代码非常easy。看看凝视就应该明确了。
最后附上源码:下载地址
推荐阅读
- android项目 之 记事本(13) ----- 查看图片及播放录音
- Android 正则表达式验证手机号姓名(包含少数民族)身份证号
- 移动APP测试用例设计实践经验(转载)
- 微信app支付android客户端以及.net服务端实现
- App开发定制前需要做哪些规划()
- 移动讲堂(如何避免App外包被坑())
- Android Studio中查看类的继承关系
- Appium环境搭建
- nginx配置https及Android客户端访问自签名证书