项目中存在复杂的后台操作且不能影响ui线程显示效果,因些就有很多事情需要后台处理。因此android中提出单线程模型开发。


在开发Android应用时必须遵守单线程模型的原则:
Android UI 操作并不是线程安全的并且这些操作必须在UI线程中执行。


在单线程模型中始终要记住两条法则:
1、不要阻塞UI线程
2、确保只在UI线程中访问Android UI工具包
当一个程序第一次启动时,Android会同时启动一个对应的主线程,主线程主要负责处理与UI相关的事件,
如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。
所以主线程通常又被叫做UI线程。


而在Android中实现异步任务的机制有两种方式: Handler 及 AsyncTask

Handler方式:
需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新.

AsyncTask方式:
使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务.

Handler 的用法在 http://blog.csdn.net/andyhuabing/article/details/7368217 中已学习过了,这里只对异步任务类进行说明。


AsyncTask 的定义:

public abstract class AsyncTask<Params, Progress, Result>

三个泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。


几个重载方法说明:
1、 execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2、 onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3、 doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收
输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
4、 onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接
将进度信息更新到UI组件上。
5、 onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,
直接将结果显示到UI组件上。


下面将 Handler 及 AsyncTask 两者在一起进行使用,给出一个实际的测试例子:


首先编写一个异步任务类:

注意其实例化的参数:

AsyncTask<String, Integer, String> 

package com.example.test;import java.io.ByteArrayOutputStream;import java.io.InputStream;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.content.Context;import android.os.AsyncTask;import android.util.Log;public class TestAsyncTask extends AsyncTask<String, Integer, String> {static final String TAG = "testAsyncTask";AsyncTaskCallback cb = null;public static final int PRE_EVENT = 1;public static final int POST_EVENT = 2;public static final int CACEL_EVENT = 3;public static interface AsyncTaskCallback {// 显示结果void onAsyncResult(int e, String s);// 显示进度条void onAsyncProcess(Integer pi);}public TestAsyncTask(Context c, AsyncTaskCallback cb) {this.cb = cb;}@Overrideprotected void onPreExecute() {Log.i(TAG, "onPreExecute called");cb.onAsyncResult(PRE_EVENT, "loading...");}@Overrideprotected void onPostExecute(String result) {Log.i(TAG, "onPostExecute called: result : " + result);cb.onAsyncResult(POST_EVENT, result);}@Overrideprotected void onCancelled() {Log.i(TAG, "onCancelled called");cb.onAsyncResult(CACEL_EVENT, "cancle loading");}@Overrideprotected void onProgressUpdate(Integer... values) {Log.i(TAG, "onProgressUpdate called progress:" + values[0]);cb.onAsyncProcess(values[0]);}// doInBackground方法内部执行后台任务@Overrideprotected String doInBackground(String... params) {Log.i(TAG, "doInBackground called: params : " + params[0]);try {HttpClient client = new DefaultHttpClient();HttpGet get = new HttpGet(params[0]);HttpResponse response = client.execute(get);if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {HttpEntity entity = response.getEntity();InputStream is = entity.getContent();long total = entity.getContentLength();ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buf = new byte[512];int count = 0;int length = -1;while ((length = is.read(buf)) != -1) {baos.write(buf, 0, length);count += length;// 调用publishProgress公布进度,最后onProgressUpdate方法将被执行publishProgress((int) ((count / (float) total) * 100));// 为了演示进度条,休眠100毫秒Thread.sleep(100);}return new String(baos.toByteArray(), "utf-8");}} catch (Exception e) {Log.e(TAG, e.getMessage());}return null;}}

测试用例:

package com.example.test;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.Menu;import android.view.View;import android.webkit.WebView;import android.widget.Button;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;import com.example.test.TestAsyncTask.AsyncTaskCallback;public class MainActivity extends Activity {static final String TAG = "MainActivity";private Button execute;private Button cancel;private ProgressBar progressBar;private TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initview();loading();}@Overridepublic 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;}void initview() {execute = (Button) findViewById(R.id.execute);cancel = (Button) findViewById(R.id.cancel);progressBar = (ProgressBar) findViewById(R.id.progress_bar);textView = (TextView) findViewById(R.id.text_view);progressBar.setProgress(0);execute.setEnabled(true);cancel.setEnabled(false);}AsyncTaskCallback cb = new AsyncTaskCallback() {@Overridepublic void onAsyncResult(int e, String s) {Log.i(TAG, "onAsyncResult event:" + e + " result:" + s);Message msg = Message.obtain();msg.what = 1;msg.arg1 = e;msg.obj = (Object) s;testH.sendMessage(msg);}@Overridepublic void onAsyncProcess(Integer pi) {Message msg = Message.obtain();msg.what = 2;msg.obj = (Object) pi;testH.sendMessage(msg);}};TestHandle testH = new TestHandle();TestAsyncTask task = null;void loading() {execute.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// 注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常task = new TestAsyncTask(MainActivity.this.getApplicationContext(), cb);//task.execute("http://blog.csdn.net/andyhuabing/article/details/7368217");task.execute("http://www.baidu.com/");execute.setEnabled(false);cancel.setEnabled(true);}});cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 取消一个正在执行的任务,onCancelled方法将会被调用task.cancel(true);}});}class TestHandle extends Handler {@Overridepublic void handleMessage(Message msg) {Log.i(TAG, "handleMessage msg:" + msg.what);switch (msg.what) {case 1:textView.setText((String) msg.obj);Toast.makeText(MainActivity.this.getApplicationContext(),(String) msg.obj, Toast.LENGTH_LONG).show();if (msg.arg1 == TestAsyncTask.PRE_EVENT) {} else if (msg.arg1 == TestAsyncTask.POST_EVENT) {execute.setEnabled(true);cancel.setEnabled(false);} else if (msg.arg1 == TestAsyncTask.CACEL_EVENT) {progressBar.setProgress(0);execute.setEnabled(true);cancel.setEnabled(false);}break;case 2:progressBar.setProgress((Integer) msg.obj);textView.setText("loading..." + (Integer) msg.obj + "%");break;default:break;}}};}

layout 布局文件如下:

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:orientation="vertical"      android:layout_width="fill_parent"      android:layout_height="fill_parent">      <Button          android:id="@+id/execute"          android:layout_width="fill_parent"          android:layout_height="wrap_content"          android:text="execute"/>      <Button          android:id="@+id/cancel"          android:layout_width="fill_parent"          android:layout_height="wrap_content"          android:enabled="false"          android:text="cancel"/>      <ProgressBar           android:id="@+id/progress_bar"           android:layout_width="fill_parent"           android:layout_height="wrap_content"           android:progress="0"          android:max="100"          style="?android:attr/progressBarStyleHorizontal"/>      <ScrollView          android:layout_width="fill_parent"           android:layout_height="wrap_content">          <TextView              android:id="@+id/text_view"              android:layout_width="fill_parent"               android:layout_height="wrap_content"/>      </ScrollView>    <WebView        android:id="@+id/webView"        android:layout_width="match_parent"        android:layout_height="354dp" />    </LinearLayout> 


更多相关文章

  1. 如何在后台运行Linux命令?
  2. Android(安卓)Service 两种编写及应用
  3. Android面试题整理-3
  4. android 消息传递机制进阶EventBus的深入探究
  5. Android(安卓)方法数 65k 问题
  6. Android配置启动页
  7. Android(安卓)壁纸设置代码 详解
  8. Android中FTP服务器、客户端搭建以及SwiFTP、ftp4j介绍
  9. android 一个小例子说明handler和AlertDialog的简单使用

随机推荐

  1. Android中Intent组件详解 .
  2. Android(安卓)input处理机制(四)线程安全
  3. Android 查看/data/data文件夹并取回文件
  4. 2019最新Android算法相关面试大全,请查收
  5. 博文视点大讲堂35期《Google Android创赢
  6. 【Sublinux】Station P1在Android上使用
  7. 详解Android首选项框架的使用
  8. android获取string.xml的值
  9. Android之Menu基本使用(显示图标icon)
  10. 使用QQ2013时连接Android物理设备Eclipse