Android之线程使用AsyncTask异步任务(一)

线程的概念

手机客户端有个概念,即UI主线程,我们能看到的按钮控件等其实都是有一条UI的主线程在运行着。如果有一条UI主线程在运行,在UI的主线程中我们去访问网络资源(存数据或者取数据),我们会遇到阻塞的现象。学习线程的好处:UI主线程是用于负责展示UI控件的,我们要完成耗时任务的操作,比如提交数据或者存数据应该在另外一个线程完成。


如果我们让不同的组件在这里运行,我们应该让他运行在独立的线程中,比如说,UI主线程在这运行着,同时我又下文件,又上传数据,又看电影,这些分别不同的操作应该放在独立的线程操作,不应该放在一个线程中操作。

系统不会给我们创建一个独立的线程给每一个组件,也就是说,当我们点击一个按钮,访问网络图片时(这是在主线程中操作的),我们期望的是不改在主线程中操作,系统不会帮我们创建的。如果不从主线程中分离开,这样就会有好多组件的操作在主线程中操作,会导致主线程任务繁忙,尤其是耗时操作的时候(导致阻塞),反应超过5s就会可能产生ANR(application not responding)。


所以,UI主线程不能当做工作线程,Android中的线程模式应该是单线程的模式。

①不要阻塞UI主线程(不在UI线程访问网络等)。

②不在UI以外的线程当中访问UI(UI的概念就是在主线程中呈现的)。


异步和同步的区别:

看下图(参考别人的)



处理复杂的工作线程两种机制:Handler或者AsyncTask


AsyncTask(异步任务)允许我们在用户UI上执行异步的工作,这个执行可能是个阻塞的操作,它可以把结果发布给UI。举个例子,当我们下载一个文件时,刻度条就是UI,我们一边下载,一边让刻度条走动来达到更新UI的效果。


异步任务操作的方法:

声明一个类MyTask继承(extends)AsyncTask(抽象类)->实现doInBackground()方法->为了更新UI实现onPostExecute()方法->把这些结果从doInBackground()方法中传递到UI上->执行这个异步任务,只需在UI线程中调用execute()方法。


AsyncTask异步任务分为三个参数Params,Progress和Result,四个步骤调用onPreExecute,doInBackground,onProgressUpdate和onPostExecute。

三个参数:

①Params:这个参数类型表示我们执行异步任务要发送的参数,也就是说,这个异步任务要执行什么东西,比如访问网络这里就是一个网址。

Progress:这个参数是一个进度单位的类型,这个进度单位是在后台计算完成之后被发布的单位。

Result:表示后台执行的返回结果。

并非所有的异步任务都要用到三个参数,如果不用就用Void类型代替。

四个步骤:

执行一个完整的异步任务,要依次经历以下四个步骤(步骤是有顺序的①②③④顺序执行),其中,doInBackground()方法是必须要执行的,即继承了AsyncTask方法就一定要实现doInBackground方法,也就是说你得做一件事情,否则异步任务没有意义

onPreExecute(),异步任务被执行之前执行,UI展示的时候执行。这个步骤通常用来构建一个异步任务,比如,我们可以显示一个进度条给用户看。

doInBackground(Params...),在onPreExecute()之后doInBackground()会立即执行,这个步骤通常用来执行后台的操作(耗时操作)。Params...这个参数表示我们要执行的参数。参数的结果会被计算出来,并且通过这个步骤返回给最后一个步骤onPostExecute()。在这个步骤中间我们可以用publicProgress(Progress...)来发布一个或多个的进度单位,在第三个步骤onProgressUpdate()被调用时,把这个值发布给UI线程。

onProgressUpdate(Progress...)

onPostExecute(Result),后台计算出结果后会执行在UI上面,UI上的结果通常会来自doInBackground(Params...)。

注意:假设我不使用提示框第①个步骤不需要调用,如果我不需要把这个结果更新给UI第④个步骤不需要调用,如果我在下载的时候不更新进度条,第③个步骤不需要,这就是为什么一个类继承了AsyncTask方法的时候仅仅需要doInBackground方法。

下面举个例子:点击下载网络图片按钮,实现下载网络图片功能

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.android_asynctask_downloadimage.MainActivity" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="60dp"
        android:layout_marginTop="40dp"
         />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="下载网络图片" />
	
</RelativeLayout>

MainActivity.java

package com.example.android_asynctask_downloadimage;

import java.io.IOException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.support.v7.app.ActionBarActivity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends ActionBarActivity {

	private Button btn1;
	private ImageView imageView1;
	private final String IMAGE_PATH="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
	private ProgressDialog dialog;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn1=(Button) this.findViewById(R.id.button1);
		imageView1=(ImageView) this.findViewById(R.id.imageView1);
		dialog=new ProgressDialog(MainActivity.this);
		dialog.setTitle("提示");
		dialog.setCancelable(false);
		dialog.setMessage("正在下载图片,请等待...");
		
		btn1.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new MyTask().execute(IMAGE_PATH);//执行异步任务
			}
		});//点击这个按钮下载图片,需要访问网络,记得在清单文件AndroidManifest.xml中加授权android.permission.INTERNET
	}

	/**
	 * 异步任务执行网络下载图片
	 * @author liuya
	 *
	 */
	public class MyTask extends AsyncTask<String, Integer, byte[]>{

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			dialog.show();
		}
		
		/**
		 * 后台访问网络
		 */
		@Override
		protected byte[] doInBackground(String... params) {
			// TODO Auto-generated method stub
			HttpClient httpClient=new DefaultHttpClient();
			HttpGet httpGet=new HttpGet(params[0]);//可变参数,三个点代表可变参数
			byte[] result=null;
			try {
				HttpResponse httpResponse=httpClient.execute(httpGet);
				if(httpResponse.getStatusLine().getStatusCode()==200){
					result=EntityUtils.toByteArray(httpResponse.getEntity());
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				httpClient.getConnectionManager().shutdown();
			}
			
			return result;
		}
		
		/**
		 * 更新UI
		 */
		@Override
		protected void onPostExecute(byte[] result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
			Bitmap bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);
			imageView1.setImageBitmap(bitmap);
			dialog.dismiss();
		}
		
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
}

效果图如下








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值