android 解决假死问题

转自:http://406547509.blog.163.com/blog/static/456753862010112914328899/

 

是我们在开发Android程序时遇到较耗时任务的处理,如I/O访问的数据库操作、网络访问等情况时造成UI假死等问题,通过 AsyncTask可以很好的解决这个问题,就今天以在Android中执行Downloader.downloadFile(url),可能会堵塞整个界面。显然这会影响用户体验,我们如何解决这个问题呢?

  方法一、

  创建一个新的线程执行我们的任务,使用Thread类,在 run(){}中写入任务代码,比如:

  new Thread(new Runnable() {

  public void run() {

  Downloader.downloadFile(url);

  }

  }).start();

  但使用Thread会产生一些意想不到的问题,需要程序员用更多的代码手动的维护它。

  方法二: Android SDK为我们提供了一个后台任务的处理工具AsyncTask。AsyncTask就是一个封装过的后台任务类顾名思义就是异步任务,方便我们维护,Android开发网提示这样的好处可以解决一些线程安全问题,AsyncTask直接继承于Object类,位置为 android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载四个方法(至少重载一个)。

  三个泛型:

  Param ,任务执行器需要的数据类型

  Progress 后台计算中使用的进度单位数据类型

  Result 后台计算返回结果的数据类型

  有些参数是可以设置为不使用的,只要传递为Void型即可,比如AsyncTask

  四个步骤:

  onPreExecute(),执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。

  doInBackground(Params...),后台进程执行的具体计算在这里实现,doInBackground(Params...)是AsyncTask的关键,此方法必须重载。在这个方法内可以使用 publishProgress(Progress...)改变当前的进度值。

  onProgressUpdate(Progress...),运行于UI线程。如果在doInBackground(Params...) 中使用了publishProgress(Progress...),就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。

  onPostExecute(Result),运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。

  Java代码

  public class main extends Activity {

ImageView imageView01;

  TextView textView;

  @Override

  public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  textView = (TextView) this.findViewById(R.id.TextView01);

  imageView01 = (ImageView) this.findViewById(R.id.ImageView01);

  GetImage getImage = new GetImage();

  getImage.execute("http://hi.csdn.net/attachment/201010/27/0_1288149117Yk8W.gif");

  }

  private class GetImage extends AsyncTask {

  public GetImage() {

  super();

  // TODO Auto-generated constructor stub

  }

  @Override

  protected void onCancelled() {

  Log.i("czb", "onCancelled is running...");

  super.onCancelled();

  }

  @Override

  protected void onPostExecute(Object result) {

  /*

  * 此方法在主线程执行,任务执行的结果作为此方法的参数返回

  */

  Log.i("czb", "onPostExecute is running...");

  Log.i("czb", "result == null ? " + (result == null));

  imageView01.setImageBitmap((Bitmap)result);

  super.onPostExecute(result);

  }

  @Override

  protected void onPreExecute() {

  /*

  * 执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件

  */

  Log.i("czb", "onPreExecute is running...");

  super.onPreExecute();

  }

  @Override

  protected void onProgressUpdate(Object... values) {

  /*

  * 此方法在主线程执行,用于显示任务执行的进度。

  */

  Log.i("czb", "onProgressUpdate is running...");

  // 由publishProgress传递的值

  Log.i("czb", "values " + values[0]);

  super.onProgressUpdate(values);

  }

  @Override

  protected Object doInBackground(Object... params) {

/*

  * 此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。

  * 在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

  */

  Log.i("czb", "doInBackground is running...");

  try {

  Bitmap bitmap;

  HttpClient client = new DefaultHttpClient();

  // params[0]代表连接的url

  URI uri = URI.create((String) params[0]);

  HttpGet get = new HttpGet(uri);

  HttpResponse response = client.execute(get);

  HttpEntity entity = response.getEntity();

  long length = entity.getContentLength();

  Log.i("czb", " " + length);

  InputStream in = entity.getContent();

  if (in != null) {

  ByteArrayOutputStream baos = new ByteArrayOutputStream();

  /*byte[] buf = new byte[128];

  int ch = -1;

  int count = 0;

  while ((ch = in.read(buf)) != -1) {

  baos.write(buf, 0, ch);

  count += ch;

  if (length > 0) {

  // 如果知道响应的长度,调用publishProgress()更新进度

  // onProgressUpdate读取进度

  publishProgress((int) ((count / (float) length) * 100));

  }

  // 为了在模拟器中清楚地看到进度,让线程休眠100ms

  //Thread.sleep(100);

  }*/

  bitmap = BitmapFactory.decodeStream(in);

  in.close();

  baos.close();

  return bitmap;

  }

  } catch (Exception e) {

  e.printStackTrace();

  }

  return null;

  }

  }

  }

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页