当前位置: 代码迷 >> Android >> Android镜头UI中的线程约束
  详细解决方案

Android镜头UI中的线程约束

热度:59   发布时间:2016-05-01 10:48:11.0
Android画面UI中的线程约束

转自:http://blog.csdn.net/yihui823/article/details/6722784

?

这是我自己提炼的一句简单说法:

在非UI主控线程中,不得修改UI的显示。

?

主要的意思,就是在UI主控线程中,我们的代码可以随意改变UI各个对象的显示效果,包括文字、是否可见、大小等等属性。

?

什么是主控线程?

??? 这么简单的说吧,进入onCreate、onResume等系统调用的函数的时候,这个时候就是主控线程。

??? 当然是系统调用进来的,不是我们自己的代码调用onCreate等函数。

这也包括按钮等控件的事件监听,例如onClick函数等。

那么相对应的,不在这些函数里调用的代码,执行进来的就不是UI主控线程。

这个时候,系统会抛出异常:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

?

这个限制在java本身的swing中也是存在的。如果允许了任意线程去改变UI的显示,那么画面一定会乱套的。

以下是一个错误的代码:

?

?

[java]?view plaincopy
  1. public?class?TemppjActivity?extends?Activity?{??
  2. ????/**?Called?when?the?activity?is?first?created.?*/??
  3. ????@Override??
  4. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  5. ????????super.onCreate(savedInstanceState);??
  6. ???
  7. ????????getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,???WindowManager.LayoutParams.FLAG_FULLSCREEN);??
  8. ????????requestWindowFeature(Window.FEATURE_NO_TITLE);??
  9. ?????????
  10. ????????setContentView(R.layout.main);??
  11. ?????????
  12. ????????final?Button?btn?=?(Button)?findViewById(R.id.btn);??
  13. ????????btn.setOnClickListener(new?OnClickListener()?{??
  14. ???????????@Override??
  15. ???????????public?void?onClick(View?v)?{??
  16. ??????????????btn.setText("I?Clicked!");??
  17. ???????????}??
  18. ????????});??
  19. ?????????
  20. ????????final?DateFormat?f?=?DateFormat.getDateTimeInstance();??
  21. ?????????
  22. ????????TimerTask?t?=?new?TimerTask()?{??
  23. ???????????@Override??
  24. ???????????public?void?run()?{??
  25. ??????????????<span?style="color:#ff0000;">btn.setText(f.format(new?Date()));</span>??
  26. ???????????}??
  27. ????????};??
  28. ?????????
  29. ????????Timer?ti?=?new?Timer();??
  30. ????????ti.schedule(t,?0,?5000);??
  31. ????}??
  32. }??



?

?

看红色的这一行,就是在一个定时运行的线程中去控制按钮的显示文本。这个程序运行就会有CalledFromWrongThreadException异常出现。

?

那么,如果我们有这个需求怎么办?能不能做到呢?当然是可以做到的。这个时候,就需要用到:Handler

我们先看代码需要改成什么样:

?

?

[java]?view plaincopy
  1. public?class?TemppjActivity?extends?Activity?{??
  2. ?????
  3. ????private?Handler?handle;??
  4. ?????
  5. ????/**?Called?when?the?activity?is?first?created.?*/??
  6. ????@Override??
  7. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  8. ????????super.onCreate(savedInstanceState);??
  9. ???
  10. ????????getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,???WindowManager.LayoutParams.FLAG_FULLSCREEN);??
  11. ????????requestWindowFeature(Window.FEATURE_NO_TITLE);??
  12. ?????????
  13. ????????setContentView(R.layout.main);??
  14. ???
  15. ????????final?Button?btn?=?(Button)?findViewById(R.id.btn);??
  16. ????????final?DateFormat?f?=?DateFormat.getDateTimeInstance();??
  17. ?????????
  18. ????????handle?=?new?Handler()?{??
  19. ?????????public?void?handleMessage(Message?msg)?{???
  20. ???????????????btn.setText(f.format(new?Date()));??
  21. ?????????????};??
  22. ????????};??
  23. ?????????
  24. ????????btn.setOnClickListener(new?OnClickListener()?{??
  25. ???????????@Override??
  26. ???????????public?void?onClick(View?v)?{??
  27. ??????????????btn.setText("I?Clicked!");??
  28. ???????????}??
  29. ????????});??
  30. ?????????
  31. ?????????
  32. ????????TimerTask?t?=?new?TimerTask()?{??
  33. ???????????@Override??
  34. ???????????public?void?run()?{??
  35. ??????????????handle.sendEmptyMessage(0);??
  36. ???????????}??
  37. ????????};??
  38. ?????????
  39. ????????Timer?ti?=?new?Timer();??
  40. ????????ti.schedule(t,?0,?5000);??
  41. ????}??
  42. }??



?


也就是说,我们在非UI主控线程中,如果需要修改UI,则向UI主界面发送一个消息。

handle.sendEmptyMessage(0);

消息可以很复杂,我们这里只是发送一个空消息过去。

在主控线程中,会由handler来处理这些消息,收到消息后来处理各个控件的改变。

在handleMessage函数中我们可以具体控制UI应该如何改变。

  相关解决方案