码迷,mamicode.com
首页 > 移动开发 > 详细

android AsyncTask使用

时间:2015-08-09 22:37:03      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:android   异步线程   网络请求   io处理   


         /** 
	 * 作者:crazyandcoder 
	 * 联系: 
	 *      QQ   : 275137657 
	 *      email: lijiwork@sina.com 
	 * 转载请注明出处! 
	 */


异步任务 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.)

     大概意思就是说:

  1. 必须在UI主线程中创建AsyncTask的实例。
  2. excute()方法必须在UI主线程中调用。
  3. 不需要手动调用onPreExcute、doInBackground、onProgressUpdate、onPostExcute四个方法。
  4. 一个AsyncTask实例只能执行一个任务。
四、实例Demo
       我们先看一下效果,然后再来讲解一下具体的实现过程。本次demo主要实现的是异步加载一张网络图片,并在加载过程中显示加载的进度百分比,主要涉及到一些IO操作以及网络请求等知识点。

技术分享 技术分享 技术分享

              图1                                                 图2                                        图3


      图1显示的是功能,主要是点击button后进入加载网络图片页面;

      图2显示的是加载网络图片过程中的进度百分比;

      图3显示的是当加载进度百分比为100%时,显示要加载的网络图片。


      下面我们来分析一下具体的实现代码:

       主界面的布局就不贴了,主要就是一个button按钮,然后在MainActivity中实现页面跳转,我们主要来看看ImageTest.class 中是如何实现加载网络图片的。

       首先是xml布局,布局很简单,一个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);
		}
	}

}

         代码很简单,看看注释就应该明白了。

      最后附上源代码:下载地址


版权声明:本文为博主原创文章,未经博主允许不得转载。

android AsyncTask使用

标签:android   异步线程   网络请求   io处理   

原文地址:http://blog.csdn.net/liji_xc/article/details/47313069

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!