android AsyncTask使用
Posted wzzkaifa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android AsyncTask使用相关的知识,希望对你有一定的参考价值。
/** * 作者:crazyandcoder * 联系: * QQ : 275137657 * email: [email protected] * 转载请注明出处!*/
异步任务 AsyncTask使用
android中实现异步机制主要有Thread加Handler和AsyncTask,今天主要记录一下AsyncTask的学习过程。以备以后之需。
一、构建AsyncTask子类的參数
AsyncTask<Params,Progress,Result>是一个抽象类。
通经常使用于被继承,继承AsyncTask须要指定例如以下三个泛型參数。
- Params: 启动任务时输入參数的类型。
- Progress:后台任务运行过程中进度之的类型。
- Result: 后台运行任务完毕后返回结果的类型。
- 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,在这里面主要是载入网络图片的主题代码。代码中凝视写的都一清二楚。直接上代码了。
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, "mImgUrl is " + 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 = 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 AsyncTask使用的主要内容,如果未能解决你的问题,请参考以下文章
片段中的 Asynctask 未到达 onPostExecute
Android:尝试通过 AsyncTask 加载 videoview 时出现 NullPointerException [重复]