线程
来源:互联网 发布:淘宝上的拍卖是真的吗 编辑:程序博客网 时间:2024/06/14 14:48
今天在论坛上看到一些关于线程的帖子,我觉得与我理解的有些差异,拿上来与大家讨论下
关于android的线程模型:当一个android的应用运行后, 就会有一个UI的main线程启动,这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与android控件交互的线程。比如,当你在屏幕上的EditText上输入文字,UI线程会把这个事件分发给刚输入文字的EditText,紧接会向事件队列发送一个更新(invalidate)请求。UI线程会把这个请求移出事件队列并通知EditText在屏幕上重新绘制自身。
这种单线线程模型就会使得android的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:
1. Bitmap b = loadImageFromNetwork();
复制代码
这个操作非常耗时, 在这种情况下你会发现, 界面僵死在那里并且android在系统5秒中后没有反应,会显示一个关闭或等待的错误。
也许我们可以使用一个新的Thread来解决它
1. new Thread(new Runnable() {
2. public void run() { Bitmap b = loadImageFromNetwork();
3. mImageView.setImageBitmap( b );
4. }
5. }).start();
复制代码
但这样会发生一些很难察觉的错误, 因为我们知道UI线程不是线程安全的。当然有很多种方法来处理这个问题:
android提供了几种在其他线程中访问UI线程的方法。
• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder
1. new Thread( new Runnable() {
2. public void run() {
3. final Bitmap b = loadImageFromNetwork();
4. mImageView.post( new Runnable() {
5. mImageView.setImageBitmap( b );
6. });
7. }
8. }).start();
复制代码
这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。为了解决这个问题,android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。
我就拿加载网络图片举个例子:
1. public class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. Log.v("img", e.getMessage());
19. return null;
20. }
21. }
22. this.gView = view;
23. return bmp;
24. }
25. protected void onPostExecute(Bitmap bm) {
26. if (bm != null) {
27. this.gView.setImageBitmap(bm);
28. this.gView = null ;
29. }
30. }
31.
32. }
复制代码
在Activity中直接调用
1. if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
2. img.setImageResource(R.drawable.icon_app);
3. img.setTag(imgpath);
4. try{
5. new CanvasImageTask().execute(img);
6. img.setDrawingCacheEnabled(true);
7. }catch (Exception e) {
8. Log.e("error", "RejectedExecutionException in content_img: " + imgpath);
9. }
10. }
复制代码
这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用callback在图片加载完后进行回调
1. public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. e.printStackTrace();
19. Log.v("img", e.getMessage());
20. Message msg = new Message();
21. msg.what = 0;
22. handleMessage(msg);
23. return null;
24. }
25. }
26. this.gView = view;
27. return bmp;
28. }
29. protected void onPostExecute(Bitmap bm) {
30. if (bm != null) {
31. this.gView.setImageBitmap(bm);
32. this.gView.setTag(bm);
33. this.gView = null ;
34. Message msg = new Message();
35. msg.what = 1;
36. handleMessage(msg);
37. }
38. }
39. public boolean handleMessage(Message msg) {
40. // TODO Auto-generated method stub
41. return false;
42. }
43.
44. }
复制代码
在Activity中直接调用
1. new CanvasImageTaskCall(){
2. @Override
3. public boolean handleMessage(Message msg) {
4. switch (msg.what) {
5. case 0:
6. Log.i("test", "图片加载失败");
7. break;
8. case 1:
9. Log.i("test", "图片加载成功");
10. break;
11. default:
12. break;
13. }
14. saveButton.setTextColor(Color.WHITE);
15. saveButton.setClickable(true);
16. bitmap = (Bitmap) imageView.getTag();
17. return super.handleMessage(msg);
18. }
19. }.execute(img);
关于android的线程模型:当一个android的应用运行后, 就会有一个UI的main线程启动,这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与android控件交互的线程。比如,当你在屏幕上的EditText上输入文字,UI线程会把这个事件分发给刚输入文字的EditText,紧接会向事件队列发送一个更新(invalidate)请求。UI线程会把这个请求移出事件队列并通知EditText在屏幕上重新绘制自身。
这种单线线程模型就会使得android的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:
1. Bitmap b = loadImageFromNetwork();
复制代码
这个操作非常耗时, 在这种情况下你会发现, 界面僵死在那里并且android在系统5秒中后没有反应,会显示一个关闭或等待的错误。
也许我们可以使用一个新的Thread来解决它
1. new Thread(new Runnable() {
2. public void run() { Bitmap b = loadImageFromNetwork();
3. mImageView.setImageBitmap( b );
4. }
5. }).start();
复制代码
但这样会发生一些很难察觉的错误, 因为我们知道UI线程不是线程安全的。当然有很多种方法来处理这个问题:
android提供了几种在其他线程中访问UI线程的方法。
• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder
1. new Thread( new Runnable() {
2. public void run() {
3. final Bitmap b = loadImageFromNetwork();
4. mImageView.post( new Runnable() {
5. mImageView.setImageBitmap( b );
6. });
7. }
8. }).start();
复制代码
这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。为了解决这个问题,android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。
我就拿加载网络图片举个例子:
1. public class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. Log.v("img", e.getMessage());
19. return null;
20. }
21. }
22. this.gView = view;
23. return bmp;
24. }
25. protected void onPostExecute(Bitmap bm) {
26. if (bm != null) {
27. this.gView.setImageBitmap(bm);
28. this.gView = null ;
29. }
30. }
31.
32. }
复制代码
在Activity中直接调用
1. if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
2. img.setImageResource(R.drawable.icon_app);
3. img.setTag(imgpath);
4. try{
5. new CanvasImageTask().execute(img);
6. img.setDrawingCacheEnabled(true);
7. }catch (Exception e) {
8. Log.e("error", "RejectedExecutionException in content_img: " + imgpath);
9. }
10. }
复制代码
这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用callback在图片加载完后进行回调
1. public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. e.printStackTrace();
19. Log.v("img", e.getMessage());
20. Message msg = new Message();
21. msg.what = 0;
22. handleMessage(msg);
23. return null;
24. }
25. }
26. this.gView = view;
27. return bmp;
28. }
29. protected void onPostExecute(Bitmap bm) {
30. if (bm != null) {
31. this.gView.setImageBitmap(bm);
32. this.gView.setTag(bm);
33. this.gView = null ;
34. Message msg = new Message();
35. msg.what = 1;
36. handleMessage(msg);
37. }
38. }
39. public boolean handleMessage(Message msg) {
40. // TODO Auto-generated method stub
41. return false;
42. }
43.
44. }
复制代码
在Activity中直接调用
1. new CanvasImageTaskCall(){
2. @Override
3. public boolean handleMessage(Message msg) {
4. switch (msg.what) {
5. case 0:
6. Log.i("test", "图片加载失败");
7. break;
8. case 1:
9. Log.i("test", "图片加载成功");
10. break;
11. default:
12. break;
13. }
14. saveButton.setTextColor(Color.WHITE);
15. saveButton.setClickable(true);
16. bitmap = (Bitmap) imageView.getTag();
17. return super.handleMessage(msg);
18. }
19. }.execute(img);
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 线程
- 敲代码诗
- 提问的智慧
- Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类
- YUI Compressor Maven Plugin介绍
- Internet Explorer 编程简述(十一)实现完美的Inplace Drag & Drop——“超级拖放”
- 线程
- activitygroup
- Internet Explorer 编程简述(十二)正确地设置和转移焦点
- 使用ActivityGroup来切换Activity和Layout
- bluez蓝牙协议栈交叉编译移植教程(附带视频下载地址)
- 布局像素单位
- android ueventd 本地native部分源码分析
- 一些技巧
- javascript 鼠标拖拉画图