android 的线程模型:当一个 android 的应用运行后,就会有一个 UI 的 main 线程启动 , 这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与 android 控件 交互的线程。比如,当你在屏幕上的 EditText 上输入文字, UI 线程会把这个事件分发给刚输入文字的 EditText ,紧接会向事件队列发送一个更新 ( invalidate )请求。 UI 线程会把这个请求移出事件队列并通知 EditText 在屏幕上重新绘制自身。

这种单线线程模型就会使得 android 的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:

Bitmap b =  loadImageFromNetwork();  

这个操作非常耗时, 在这种情况下你会发现 , 界面僵死在那里并且 android 在系统 5 秒中后没有反应,会显示一个关闭或等待的错误。

也许我们可以使用一个新的 Thread 来解决它

new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap( b );
}
}).start();

但这样会发生一些很难察觉的错误, 因为我们知道 UI 线程不是线程安全的。当然有很多种方法来处理这个问题:

android 提供了几种在其他线程中访问 UI 线程的方法。

• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder

new Thread( new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post( new Runnable() {
mImageView.setImageBitmap( b );
});
}
}).start();

这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI 时这会变得更糟糕。为了解决这个问题,android 提供了一个工具类:AsyncTask ,它使创建需要与用户界面交互的长时间运行的任务变得更简单。

就拿加载网络图片举个例子:

ublic class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
private ImageView gView ; protected Bitmap doInBackground(ImageView... views) {
Bitmap bmp = null ;
ImageView view = views[0];
// 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
if (view.getTag() != null) {
try {
URL url = new URL(view.getTag().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(stream);
stream.close();
} catch (Exception e) {
Log.v("img", e.getMessage());
return null;
}
}
this.gView = view;
return bmp;
}
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
this.gView.setImageBitmap(bm);
this.gView = null ;
}
} }
在Activity中直接调用
if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
img.setImageResource(R.drawable.icon_app);
img.setTag(imgpath);
try{
new CanvasImageTask().execute(img);
img.setDrawingCacheEnabled(true);
}catch (Exception e) {
Log.e("error", "RejectedExecutionException in content_img: " + imgpath);

这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用 callback 在图片加载完后进行回调

public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
private ImageView gView ; protected Bitmap doInBackground(ImageView... views) {
Bitmap bmp = null ;
ImageView view = views[0];
// 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
if (view.getTag() != null) {
try {
URL url = new URL(view.getTag().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(stream);
stream.close();
} catch (Exception e) {
e.printStackTrace();
Log.v("img", e.getMessage());
Message msg = new Message();
msg.what = 0;
handleMessage(msg);
return null;
}
}
this.gView = view;
return bmp;
}
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
this.gView.setImageBitmap(bm);
this.gView.setTag(bm);
this.gView = null ;
Message msg = new Message();
msg.what = 1;
handleMessage(msg);
}
}
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
} }

在 Activity 中直接调用

new CanvasImageTaskCall(){
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 0:
Log.i("test", "图片加载失败");
break;
case 1:
Log.i("test", "图片加载成功");
break;
default:
break;
}
saveButton.setTextColor(Color.WHITE);
saveButton.setClickable(true);
bitmap = (Bitmap) imageView.getTag();
return super.handleMessage(msg);
}
}.execute(img);

最新文章

  1. MySQL常见错误
  2. 自定义刷新tableView
  3. 最长公共上升子序列(codevs 2185)
  4. sql server 导出的datetime结果 CAST(0x00009E0E0095524F AS DateTime) 如何向mysql,oracle等数据库进行转换
  5. python 练习 29
  6. linux下DNS设置以及解析顺序
  7. Django搭建及源码分析(二)
  8. 安装Hadoop集群的最快的软件
  9. ArrayList内元素按照字典排序
  10. 5.IP选路,动态选路
  11. ThreadPoolExecutor运行机制
  12. Windows10获取VS管理员权限总是很烦人
  13. 尝试启动 ADB 服务器时出错 解决方法
  14. http to https
  15. TcxGrid 复选框
  16. android中执行(定时任务)的方法及6位随机码的产生
  17. linux系统中关于shell变量$*与$@的区别
  18. JavaScript中的作用域以及this变量
  19. (转)MySQL Proxy使用
  20. 【树状数组】【P3608】平衡的照片

热门文章

  1. 评价早期SaaS创业公司时,投资人在关注什么?(是否有机会发展成一个平台,长期的护城河)
  2. delete 多表删除的使用(连表删除)
  3. [置顶] lvs-tun隧道模式搭建
  4. Checkbutton 和 Radiobutton
  5. boost的并发库
  6. 关于jqueryUI里的拖拽排序
  7. 查询本天气预报Web Services支持的国内外城市或地区信息
  8. VS2008常见编译错误(总结篇)
  9. Excel 用row()函数 在Excel中自动添加序号,
  10. dom 删除和清除