当前位置:文档之家› Android UI线程分析

Android UI线程分析

理解UI线程——swt, Android, 和Swing的UI机理线程在做GUI的时候, 无论是SWT, AWT, Swing 还是Android, 都需要面对UI线程的问题, UI线程往往会被单独的提出来单独对待, 试着问自己,当GUI启动的时候, 后台会运行几个线程? 比如1. SWT 从Main函数启动2. Swing 从Main函数启动3. Android 界面启动常常我们被告知, 主线程, UI线程, 因此这里很多会回答, 有两个线程, 一个线程是Main, 另外一个是UI. 如果答案是这样, 这篇文章就是写给你的。

OK, 我们以SWT为例, 设计以下方案寻找答案, 第一步, 我们看能否找到两个线程:1. 从Main中启动SWT的界面, 在启动界面前, 将Main所在的线程打印出来这里设计为Shell中嵌入一个Button2. 点击Button, 运行一个耗时很长的操作, 反复修改Button的文字, 在该线程中打印该线程的名称代码是这样的:1.publicstaticvoid main(String[] args) {2.final Display display = Display.getDefault();3.final Shell shell = new Shell();4. shell.setSize(500, 375);5. shell.setText("SWT Application");6. shell.setLayout(new FillLayout());7. btn = new Button(shell, SWT.NULL);8. btn.setText("shit");9. registerAction();10. shell.open();11. yout();12.while (!shell.isDisposed()) {13.if (!display.readAndDispatch())14. display.sleep();15. }16. shell.dispose();17. display.dispose();18.}19.privatestaticvoid registerAction() {20. btn.addMouseListener(new MouseListener() {21. @Override22.publicvoid mouseDoubleClick(MouseEvent e) {23. // TODO Auto-generated method stub24. }25. @Override26.publicvoid mouseDown(MouseEvent e) {27. methodA();28. }29. @Override30.publicvoid mouseUp(MouseEvent e) {31. }32. });33.}34./**35.* 持续的跑动, 打印线程的名称, 注意拖拽不动, 界面死掉, 直到跑完36.*/37.privatestaticvoid methodA() {38.for (int i = 0; i < count; i++) {39. haveArest(300);40. System.out.println("MethodA:" +Thread.currentThread().getName());41. btn.setText(i + "");42. }43.}haveArest方法在最后出现, 只是封装了一个让线程等待一段时间, 打印的结果都为main, 于是得到第一个重要的结论:UI所在的线程和Main所在的线程都是同一个线程。

再来推断一把:UI在哪个线程启动的, 则这个线程就是UI线程.1./**2.* @param args3.*/4.publicstaticvoid main(String[] args) {5. // TODO Auto-generated method stub6.7. Thread t = new Thread(new Runnable() {8. @Override9.publicvoid run() {10. createUI();11. }12. });13. t.start();14.}15.16.privatestaticvoid createUI()17.{18. System.out.println(Thread.currentThread().getName());19.final Display display = Display.getDefault();20.final Shell shell = new Shell();21. shell.setSize(500, 375);22. shell.setText("SWT Application");23. shell.setLayout(new FillLayout());24. Button btn = new Button(shell, SWT.NULL);25. btn.setText("shit");26. shell.open();27. yout();28.while (!shell.isDisposed()) {29.if (!display.readAndDispatch())30. display.sleep();31. }32. shell.dispose();33. display.dispose();34.}通过打印结果发现, 推论是正确的.根据铺天盖地参考书提示, 有这样一条定律:只可以存在一个UI线程验证一下, 我们的验证方式是创建两个UI线程:1./**2.* @param args3.*/4.publicstaticvoid main(String[] args) {5. // TODO Auto-generated method stub6.7. Thread t = new Thread(new Runnable() {8. @Override9.publicvoid run() {10. createUI();11. }12. });13. t.start();14.15. t = new Thread(new Runnable() {16. @Override17.publicvoid run() {18. createUI();19. }20. });21. t.start();22.23.24.}25.26.privatestaticvoid createUI()27.{28. System.out.println(Thread.currentThread().getName());29.final Display display = new Display();30.final Shell shell = new Shell();31. shell.setSize(500, 375);32. shell.setText("SWT Application");33. shell.setLayout(new FillLayout());34. Button btn = new Button(shell, SWT.NULL);35. btn.setText("shit");36. shell.open();37. yout();38.while (!shell.isDisposed()) {39.if (!display.readAndDispatch())40. display.sleep();41. }42. shell.dispose();43. display.dispose();44.}但这里确实创建了两个线程。

看来一个进程是可以创建两个线程的。

可以存在一个或者多个UI线程, 下次看到参考书这么写的时候, 可以BS它了。

之前犯了一个错误就是用Diplay display = Display.getDefault(); 这样得到的是前一个线程创建的Display,故不能创建. 造成只能创建一个UI线程的错觉当然我们的研究不能到此为止, 我们需要探究一下, 为什么总是被告知更新UI的动作要放在UI线程中?回到第一个例子中, 即:1.publicstaticvoid main(String[] args) {2.final Display display = Display.getDefault();3.final Shell shell = new Shell();4. shell.setSize(500, 375);5. shell.setText("SWT Application");6. shell.setLayout(new FillLayout());7. btn = new Button(shell, SWT.NULL);8. btn.setText("shit");9. registerAction();10. shell.open();11. yout();12.while (!shell.isDisposed()) {13.if (!display.readAndDispatch())14. display.sleep();15. }16. shell.dispose();17. display.dispose();18.}19.privatestaticvoid registerAction() {20. btn.addMouseListener(new MouseListener() {21. @Override22.publicvoid mouseDoubleClick(MouseEvent e) {23. // TODO Auto-generated method stub24. }25. @Override26.publicvoid mouseDown(MouseEvent e) {27. methodA();28. }29. @Override30.publicvoid mouseUp(MouseEvent e) {31. }32. });33.}34./**35.* 持续的跑动, 打印线程的名称, 注意拖拽不动, 界面死掉, 直到跑完36.*/37.privatestaticvoid methodA() {38.for (int i = 0; i < count; i++) {39. haveArest(300);40. System.out.println("MethodA:" +Thread.currentThread().getName());41. btn.setText(i + "");42. }43.}运行的时候拖动试试, 发现不动, 直到for循环中修改btn的操作完成.这里我们不难明白一个观点:同一个线程的情况下, 一个操作(拖动), 是需要等待另外一个操作(更新btn)完成后, 才可以进行的。

相关主题