AsyncTask的个人使用总结

包括下载图片,下载apk,以及dialog的一些处理


首先我们看下官方文档的对AsyncTask的定义。

public abstract class AsyncTask<Params, Progress, Result> {  
官方文档对这三个参数的解释如下:

Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the background computation.
Result, the type of the result of the background computation.
这三个泛型分别表示“启动任务时输入的参数”,“后台执行的进度”,“执行完成后返回的结果”。


当一个异步任务执行时,一般会通过四个步骤来完成:


onPreExecute(),这个方法在AsyncTask开启之后,第一个执行的方法,一般能用于设置任务,例如在用户界面开启一个进度条,或者开启一个dialog等等。也可不设置。

doInBackground(Params...),这一步在执行玩onPreExecute()后立即执行,耗时操作主要在这里面执行,主要接受传进来的参数,如URl等并可以返回计算结果。在执行过程中可以调用publishProgress(Progress...)来更新进度信息。

onProgressUpdate(Progress...),调用完publishProgress()方法后,可以在此方法中,直接将进度更新到UI组件上。

onPostExecute(Result),doInBackground()方法执行完成后,会调用此方法,由于doInBackgorund()方法返回的是Long类型,并且onPostExecute()方法传入的参数也是Long类型,所以,执行完doInBackground()会将结果传入到onPostExecute()方法中,对结果进行处理,例如将结果显示在UI组件上。也可以不返回结果,在onPostExecute中做自己想做的操作。


使用AsyncTask'需要遵守一下规则。



下面是拥有的方法:




下载过程都需要加上internet权限,如果涉及到我存储,也需要加上write或者read权限


1.使用AsyncTask下载多张图片到本地

package com.example.testimagedownload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import android.R.integer;
import android.R.string;
import android.app.Activity;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;

public class MainActivity extends Activity {

	private File cache;

	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
				AsyncImageTask task = new AsyncImageTask(); // 开启异步线程
				task.execute(images); // 将url数组穿进去  。如果只有一个地址,就不用传参了也行
				break;

			default:
				break;
			}
		};
	};

	// 存放图片时所用的名字
	public static final String[] imageName = { "a.jpg", "b.jpg", "c.jpg",
			"d.jpg", "e.jpg", "f.jpg", "g.jpg", "h.jpg", "i.jpg" };

	public static final String[] images = {
			"http://img0.ph.126.net/7I6B58kXE20qqCZ0utlb_g==/3291568377754692414.jpg",
			"http://pic13.nipic.com/20110317/6905997_175430392162_2.jpg",
			"http://pic33.nipic.com/20130928/3901796_081439725135_2.jpg",
			"http://s8.51cto.com/wyfs01/M00/30/B2/wKioJlJbmUDz7hXUAAAxFABWIwg573.jpg",
			"http://a1.att.hudong.com/00/30/01300542906611141741303926721_s.jpg",
			"http://pic.58pic.com/58pic/13/39/88/73C58PICs3y_1024.JPG",
			"http://imgk.zol.com.cn/ask/1/998_a9ddbf3a05c8bc1233c4132caea67e44.jpg",
			"http://pic.58pic.com/58pic/14/82/09/15R58PICirn_1024.jpg",
			"http://pic11.nipic.com/20101129/3096042_225034073400_2.jpg" };

	// public List<String> contact = new ArrayList<String>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 创建缓存目录,系统一运行就得创建缓存目录的,
		// cache = new File(Environment.getExternalStorageDirectory(), "cache");
		File dataDir = getFilesDir().getParentFile();
		cache = new File(dataDir, "applist"); 
		if (!cache.exists()) {
			cache.mkdirs();
		}
		handler.sendEmptyMessage(0);
	}

	private final class AsyncImageTask extends AsyncTask<String, Integer, Uri> {

		// 后台运行的子线程子线程
		@Override
		protected Uri doInBackground(String... params) {
			// String[] list = (String[]) params; // 可以转换,也可以不转换
			try {
				for (int i = 0; i < params.length; i++) {
					getImageURI(params[i], cache, imageName[i]);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}

		// 这个放在在ui线程中执行
		@Override
		protected void onPostExecute(Uri result) {
			super.onPostExecute(result);
		}
	}

	/*
	 * 从网络上获取图片,如果图片在本地存在的话就直接拿,如果不存在再去服务器上下载图片 这里的path是图片的地址
	 */
	public Uri getImageURI(String path, File cache, String name)
			throws Exception {
		System.out.println("ContactServicegetImageURI----->Start");

		File file = new File(cache, name);
		// 如果图片存在本地缓存目录,则不去服务器下载
		if (file.exists()) {
			return Uri.fromFile(file);// Uri.fromFile(path)这个方法能得到文件的URI
		} else {
			// 从网络上获取图片
			URL url = new URL(path);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");
			conn.setDoInput(true);
			if (conn.getResponseCode() == 200) {

				InputStream is = conn.getInputStream();
				FileOutputStream fos = new FileOutputStream(file);
				byte[] buffer = new byte[1024];
				int len = 0;
				while ((len = is.read(buffer)) != -1) {
					fos.write(buffer, 0, len);
				}
				is.close();
				fos.close();

				if (file.length() == 0) {
					// exception
				}
				// 返回一个URI对象
				return Uri.fromFile(file);
			}
		}

		System.out.println("ContactServicegetImageURI----->end");
		return null;
	}
}


2.使用AsyncTask根据url下载apk文件

(同时包括dialog提示正在下载,还有点击返回键停止下载等。还有提示下载成功或者失败功能。)

MainActivity.java

package com.example.asynctaskdemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.R.integer;
import android.app.Activity;
import android.app.Dialog;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

	private Button button1, button2;
	AsyncApkTask task = null;
	int contentLength = 0;
	String appUrlStr = "http://u.androidgame-store.com/new/game1/51/108751/lltskb_1442224809595.apk?f=baidu_1";
	String appName = "aa应用";

	public Dialog mLoading = null;
	public Dialog resultDialog = null;

	Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 0:
				// 开启下载的线程
				task = new AsyncApkTask();
				task.execute();
				break;
			case 1:
				mLoading.show();
				break;
			case 2:
				mLoading.dismiss();
				// 将目前的AsycnTask销毁,虽然这个是无效的。
				task.cancel(true);
				resultDialog = ResultDialogUtils.createLoadingDialog(
						MainActivity.this, "下载失败!", appName);
				resultDialog.show();
				sendEmptyMessageDelayed(4, 2000); // 2秒之后,销毁显示结果的dialog
				break;
			case 3:
				mLoading.dismiss();
				resultDialog = ResultDialogUtils.createLoadingDialog(
						MainActivity.this, "下载成功!", appName);
				resultDialog.show();
				sendEmptyMessageDelayed(4, 2000); // 2秒之后,销毁显示结果的dialog
				break;
			case 4:
				if (resultDialog != null && resultDialog.isShowing()) {
					resultDialog.dismiss();
				}
				break;
			default:
				break;
			}
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		button1 = (Button) findViewById(R.id.button1);
		button2 = (Button) findViewById(R.id.button2);
		button1.setOnClickListener(this);
		button2.setOnClickListener(this);

		// 初始化进度条dialog,第一个参数一定要传递MainActivity.this,
		// 如果是同getApplication,dialog无法正常显示,因为在非activity界面是无法显示dialog的
		mLoading = DialogUtils.createLoadingDialog(MainActivity.this, handler,
				appName);

	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		switch (id) {
		case R.id.button1:
			handler.sendEmptyMessage(0);
			break;
		case R.id.button2:

			break;
		default:
			break;
		}
	}

	/**
	 * 下载apk的异步线程
	 */
	public final class AsyncApkTask extends AsyncTask<String, Integer, Uri> {

		@Override
		protected void onPreExecute() {
			// 发送handler,开启正在下载的dialog
			handler.sendEmptyMessage(1);
			super.onPreExecute();
		}

		@Override
		protected Uri doInBackground(String... params) {
			try {
				// getFilesDir()获得的files的绝对路径,使用getParentFile()获得是其父路径。
				// 结果也就是/data/data/baoming
				File file = getFilesDir().getParentFile();
				// 在上面得到的路径下,创建applist目录
				File file2 = new File(file, "applist");
				if (!file2.exists()) { // 如果该目录不存在,就创建
					file2.mkdirs();
				}
				File file4 = new File(file2, "abc.apk");
				if (!file4.exists()) { // 如果文件不存在创建文件
					file4.createNewFile();
				}
				URL url = new URL(appUrlStr);

				if (isCancelled()) {
					if (file4.exists()) {
						file4.delete();
					}
					return null;
				}
				URLConnection conn = url.openConnection();
				// 获得将要下载的网络文件的大小
				contentLength = conn.getContentLength();
				InputStream is = conn.getInputStream();
				byte[] buff = new byte[contentLength];
				int length;
				OutputStream os = new FileOutputStream(file4);
				while ((length = is.read(buff)) != -1) {
					// if (isCancelled()) {
					//
					// os.close();
					// is.close();
					// file4.delete();
					//
					// return null;
					// }
					os.write(buff, 0, length);
				}
				os.close();
				is.close();
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return null;
		}

		// 这个放在在ui线程中执行
		@Override
		protected void onPostExecute(Uri result) {
			File file = getFilesDir().getParentFile();
			File file2 = new File(file, "applist");
			File file3 = new File(file2, "abc.apk");
			if (contentLength != file3.length()) { // 如果大小不一致,说明下载不成功,就将不完整的apk删除掉
				file3.delete();
				handler.sendEmptyMessage(2); // 然后发送下载失败的消息
			} else {
				handler.sendEmptyMessage(3); // 如果大小一致,说明下载成功了,显示下载成功的消息
			}
			super.onPostExecute(result);
		}
	}

}

DialogUtils.java

package com.example.asynctaskdemo;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.LinearLayout;
import android.widget.TextView;

public class DialogUtils {

	/**
	 * 创建自定义ProgressDialog
	 */
	public static Dialog createLoadingDialog(Context context,
			final Handler mHandler, String appName) {

		LayoutInflater inflater = LayoutInflater.from(context);
		View v = inflater.inflate(R.layout.layout_loading_dialog, null); // 得到加载view
		TextView app_name = (TextView) v.findViewById(R.id.dialog_app_name);
		app_name.setText("(" + appName + ")");
		LinearLayout layout = (LinearLayout) v.findViewById(R.id.dialog_view); // 加载布局
		Dialog loadingDialog = new Dialog(context, R.style.loading_dialog); // 创建自定义样式dialog
		loadingDialog.setCancelable(false); // 不可以用"返回键"取消
		loadingDialog.setContentView(layout, new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT));

		// 监听dialog界面的返回键
		loadingDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {

			@Override
			public boolean onKey(DialogInterface dialog, int keyCode,
					KeyEvent event) {
				if (keyCode == KeyEvent.KEYCODE_BACK) {
					dialog.dismiss();
					mHandler.sendEmptyMessage(2);
				}
				return false;
			}

		});

		return loadingDialog;
	}
}


ResultDialogUtils.java

package com.example.asynctaskdemo;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ResultDialogUtils {


	/**
	 * 创建自定义ProgressDialog
	 */
	public static Dialog createLoadingDialog(Context context, String result,
			String appName) {

		LayoutInflater inflater = LayoutInflater.from(context);
		View v = inflater.inflate(R.layout.layout_result_dialog, null); // 得到加载view
		TextView result_tv = (TextView) v.findViewById(R.id.result_tv);
		result_tv.setText(result);
		TextView app_name = (TextView) v.findViewById(R.id.dialog_app_name1);
		app_name.setText("(" + appName + ")");
		LinearLayout layout = (LinearLayout) v.findViewById(R.id.dialog_view); // 加载布局
		Dialog loadingDialog = new Dialog(context, R.style.loading_dialog); // 创建自定义样式dialog
		loadingDialog.setCancelable(false); // 不可以用"返回键"取消
		loadingDialog.setContentView(layout, new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT));

		return loadingDialog;
	}
}

layout_loading_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialog_view"
    android:layout_width="190dp"
    android:layout_height="120dp"
    android:background="@drawable/background_dialog"
    android:gravity="center_vertical|center"
    android:orientation="vertical"
    android:padding="12dp" >
    
    <ProgressBar
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="30dip"
        android:layout_height="30dip"
        android:indeterminateDrawable="@anim/progress_bar" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="3dp"
        android:text="正在下载中"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/dialog_app_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:textSize="16sp" />

</LinearLayout>

layout_result_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialog_view"
   android:layout_width="190dp"
    android:layout_height="120dp"
    android:background="@drawable/background_dialog"
    android:gravity="center_vertical|center"
    android:orientation="vertical"
    android:padding="12dp" >

    <TextView
        android:id="@+id/result_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="3dp"
        android:text=""
        android:textColor="#FFFFFF"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/dialog_app_name1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:textSize="16sp" />

</LinearLayout>

anim---> progress_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/isdoing"
    android:fromDegrees="0.0"
    android:pivotX="50.0%"
    android:pivotY="50.0%"
    android:toDegrees="360.0" />

styles.xml

 <style name="loading_dialog" parent="android:Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:backgroundDimEnabled">false</item>
    </style>

还有就是两张图片,自行脑补。



1.Cancelling a Task
我们可以在任何时刻来取消我们的异步任务的执行,通过调用 cancel(boolean)方法,调用完这个方法后系统会随后调用 isCancelled() 方法并且返回true。如果调用了这个方法,那么在 doInBackgroud() 方法执行完之后,就不会调用 onPostExecute() 方法了,取而代之的是调用 onCancelled() 方法。为了确保Task已经被取消了,我们需要经常调用 isCancelled() 方法来判断,如果有必要的话。
2.在使用AsyncTask做异步任务的时候必须要遵循的原则:
AsyncTask类必须在UI Thread当中加载,在Android Jelly_Bean版本后这些都是自动完成的
AsyncTask的对象必须在UI Thread当中实例化
execute方法必须在UI Thread当中调用
不要手动的去调用AsyncTaskonPreExecute, doInBackground, publishProgress, onProgressUpdate, onPostExecute方法,这些都是由Android系统自动调用的
AsyncTask任务只能被执行一次





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值