Android UI线程分析

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中嵌入一个Button

2. 点击Button, 运行一个耗时很长的操作, 反复修改Button的文字, 在该线程中打印该线程的名称

代码是这样的:

1.public

static

void 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. https://www.360docs.net/doc/5f9091548.html,yout();

12.while (!shell.isDisposed()) {

13.if (!display.readAndDispatch())

14. display.sleep();

15. }

16. shell.dispose();

17. display.dispose();

18.}

19.private

static

void registerAction() {

20. btn.addMouseListener(new MouseListener() {

21. @Override

22.public

void mouseDoubleClick(MouseEvent e) {

23. // TODO Auto-generated method stub

24. }

25. @Override

26.public

void mouseDown(MouseEvent e) {

27. methodA();

28. }

29. @Override

30.public

void mouseUp(MouseEvent e) {

31. }

32. });

33.}

34./**

35.* 持续的跑动, 打印线程的名称, 注意拖拽不动, 界面死掉, 直到跑完

36.*/

37.private

static

void 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 args

3.*/

4.public

static

void main(String[] args) {

5. // TODO Auto-generated method stub

6.

7. Thread t = new Thread(new Runnable() {

8. @Override

9.public

void run() {

10. createUI();

11. }

12. });

13. t.start();

14.}

15.

16.private

static

void 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. https://www.360docs.net/doc/5f9091548.html,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 args

3.*/

4.public

static

void main(String[] args) {

5. // TODO Auto-generated method stub

6.

7. Thread t = new Thread(new Runnable() {

8. @Override

9.public

void run() {

10. createUI();

11. }

12. });

13. t.start();

14.

15. t = new Thread(new Runnable() {

16. @Override

17.public

void run() {

18. createUI();

19. }

20. });

21. t.start();

22.

23.

24.}

25.

26.private

static

void 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. https://www.360docs.net/doc/5f9091548.html,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.public

static

void 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. https://www.360docs.net/doc/5f9091548.html,yout();

12.while (!shell.isDisposed()) {

13.if (!display.readAndDispatch())

14. display.sleep();

15. }

16. shell.dispose();

17. display.dispose();

18.}

19.private

static

void registerAction() {

20. btn.addMouseListener(new MouseListener() {

21. @Override

22.public

void mouseDoubleClick(MouseEvent e) {

23. // TODO Auto-generated method stub

24. }

25. @Override

26.public

void mouseDown(MouseEvent e) {

27. methodA();

28. }

29. @Override

30.public

void mouseUp(MouseEvent e) {

31. }

32. });

33.}

34./**

35.* 持续的跑动, 打印线程的名称, 注意拖拽不动, 界面死掉, 直到跑完

36.*/

37.private

static

void 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)完成后, 才可以进行的。

不难理解, 我们常用的做法是:

通过启动另外一个线程, 在cpu微小的间隔时间内,完成两个动作的交替

于是有了下面的代码:

1.private

static Button btn;

2.

3.private

static

final

int count = 20;

4.public

static

void main(String[] args) {

5. final Display display = Display.getDefault();

6. final Shell shell = new Shell();

7. shell.setSize(500, 375);

8. shell.setText("SWT Application");

9. shell.setLayout(new FillLayout());

10. btn = new Button(shell, SWT.NULL);

11. btn.setText("shit");

12. registerAction();

13. shell.open();

14. https://www.360docs.net/doc/5f9091548.html,yout();

15. while (!shell.isDisposed()) {

16. if (!display.readAndDispatch())

17. display.sleep();

18. }

19. shell.dispose();

20. display.dispose();

21.}

22.private

static

void registerAction() {

23. btn.addMouseListener(new MouseListener() {

24. @Override

25. public

void mouseDoubleClick(MouseEvent e) {

26. // TODO Auto-generated method stub

27. }

28. @Override

29. public

void mouseDown(MouseEvent e) {

30. methodB();

31. }

32. @Override

33. public

void mouseUp(MouseEvent e) {

34. }

35. });

36.}

37./**

38.* 为了解决拖拽不动, 界面死掉, 增加线程控制, 但产生了Invalid thread

access的问题

39.*/

40.private

static

void methodB() {

41. Thread t = new Thread(new Runnable() {

42. @Override

43. public

void run() {

44. for (int i = 0; i < count; i++) {

45. haveArest(300);

46. System.out.println("MethodB:"

47. + Thread.currentThread().getName());

48. btn.setText(i + "");

49. }

50. }

51. });

52. t.start();

53.}

但这样发现会报错, 原因是, 线程访问出错了, 因为有一个这样的规则需要我们保障:

所有的UI相关的操作, 务必保证在UI线程中更新.

为什么会有这样一条铁律? 原因是界面的消息需要分发到各大控件上面去, 如果不能保证UI在相同的线程, 分发起来就会比较复杂. UI本身占用的资源比较多. 如果在将UI 分属不同的线程, 切换起来, 将耗费大量的CPU资源.

为了保证这条, SWT 是这么做的, 利用Diplay这个变量获取UI线程, 然后在其中做UI访问和操作:

1.private

static Button btn;

2.

3.private

static

final

int count = 20;

4.public

static

void main(String[] args) {

5.final Display display = Display.getDefault();

6.final Shell shell = new Shell();

7. shell.setSize(500, 375);

8. shell.setText("SWT Application");

9. shell.setLayout(new FillLayout());

10. btn = new Button(shell, SWT.NULL);

11. btn.setText("shit");

12. registerAction();

13. shell.open();

14. https://www.360docs.net/doc/5f9091548.html,yout();

15.while (!shell.isDisposed()) {

16.if (!display.readAndDispatch())

17. display.sleep();

18. }

19. shell.dispose();

20. display.dispose();

21.}

22.private

static

void registerAction() {

23. btn.addMouseListener(new MouseListener() {

24. @Override

25.public

void mouseDoubleClick(MouseEvent e) {

26. // TODO Auto-generated method stub

27. }

28. @Override

29.public

void mouseDown(MouseEvent e) {

30. methodC();

31. }

32. @Override

33.public

void mouseUp(MouseEvent e) {

34. }

35. });

36.}

37.

38.private

static

void methodC() {

39. Thread t = new Thread(new Runnable() {

40. @Override

41.public

void run() {

42.for (int i = 0; i < count; i++) {

43. System.out.println("MethodB Thread:"

44. + Thread.currentThread().getName());

45.

46. haveArest(300);

47.final Display display = Display.getDefault();

48.final String s = i + "";

49.if ((display != null) && (!display.isDisposed())) {

50. display.asyncExec(new Runnable() {

51. @Override

52.public

void run() {

53. System.out.println("MethodB Thread

asyncExec:"

54. +

Thread.currentThread().getName());

55. btn.setText(s);

56. }

57. });

58. }

59. }

60. }

61. });

62. t.start();

63.}

64.

65.private

static

void haveArest(int sleepTime)

66.{

67.try {

68. Thread.sleep(sleepTime);

69. } catch (InterruptedException e) {

70. // TODO Auto-generated catch block

71. e.printStackTrace();

72. }

73.}

后面会继续关注Swing和Android的例子, 相信这些也是大同小异的. 关键是, UI 特殊, 但特殊性不在于它是一个额外的线程.

这样的应用其实很多, 比如我们不断刷表格的时候, 为了让界面能接受其它的响应事件, 一般都把刷表格的动作放置到另外的线程中, 用Display.asychronize()来保障其访问UI元素的安全行(即在UI中访问).

总结一下, 本文由如下结论:

UI线程和主线程,普通线程的关系

1. UI线程和Main线程没有必然联系, 从Main函数启动, 也可以从一个其它的线程启动. 启动UI的线程, 则为UI线程

2. 不允许出现两个UI线程. 如果第一个线程启动了UI. 则第一个线程则成为UI线程. 如果第二个线程涉及UI操作, 则需要保证这个操作放在UI线程中. 否则会出现Invalid thread access错误.

SWT为什么会有Display.asyncExec(new Runnable())操作:

1. 当界面执行了长时段的UI操作, 比如进度条, 此时如果把更新UI的操作放在唯一的UI线程中执行, 那么本线程将全部消耗CPU资源, 造成界面无法拖动.拖动则界面死掉MethodA()。

2. 为了解决问题1, 我们一般另外启动一个线程进行操作, 这样使得界面可以拖动, 但是UI的操作无法在其它的线程中完成, 只能在UI线程中完成,

3. Display.asyncExec(new Runnable()的目的就是将这个动作放在UI线程中完成. 这样避免报错Invalid thread access

补充SWT的知识, 很多不明白Display.asyncExec 和Display.syncExec的区别, 用个例子说明一下:

1./**

2.* 在UI线程中跑动, 注意, 在UI线程中跑动asyncExec/syncExec都不能解决

拖动的问题, 只能另起线程

3.* 才能解决如:methodC

4.*/

5.private

static

void methodD() {

6.for (int i = 0; i < count; i++) {

7. haveArest(300);

8.final Display display = Display.getDefault();

9.final String s = i + "";

10.if ((display != null) && (!display.isDisposed())) {

11. display.syncExec(new Runnable() {

12. @Override

13.public

void run() {

14. //如果是asyncExec的话, 这里到最后次才执行

15. // asyncExec要等到发起asyncExec的线程执行完毕,

他才有机会执行。在单线程的情况下, 发起asyncExec的线程和asyncExec里面的run内容都在同一个线程

16. //所以要等到asyncExec执行完毕, asyncExec中run

的东西, 才有机会执行

17. //syncExec则不同, 它务必要保证里面的方法执行后,再

回到发起syncExec方法所在的线程, 所以这里相当于一个流畅的串行操作

18. btn.setText(s);

19. System.out.println("" + s);

20. }

21. });

22. }

23. }

24.}

按注释运行下, 就会发现这里面大有玄机, 不过我这边并不是为了解决SWT的问题, 而是针对所有的UI线程来的, 所以, 不再做解释.

推荐阅读. 该牛人的长篇大作.

多谢同事章导对SWT修正的问题. 即使弥补了误导大家的观点,

Android 也是相同的原理:

1. 通过多线程避免界面假死

2. 通过Hander保证访问界面元素在UI线程中进行.

其它的一些细微差别, 不需要多讲. 原理乃一个模子出来的.

一个Android Helloworld运行起来的时候, 有四个线程

1. 传说中的Main线程

2. 另外三个都是Binder Thread, 貌似是为了跨进程通信用的监听线程.

貌似很多Android的教程都把UI线程当特殊的一个线程.

辅助阅读;

SWT组件Diaplay提供syncExec与asyncExec方法,其原型为:syncExec (Runnable runnable),asyncExec (Runnable runnable),Runnable的run方法中可以封装要执行的代码,一般而言是UI相关的代码,如更新组件显示、刷新状态等。Diaplay是和线程关联的,其所在的线程一般称谓UI线程,可以有多个UI线程,每个UI线程一个Diaplay。所有的SWT组件相关代码,必须在UI线程之中执行。

syncExec与asyncExec相同点,都是为了让Runnable封装的代码在指定的Diaplay(比如某个产成Image的diaplay) 相关的UI线程中执行。如:imgCreateDiaplay.asyncExec(runnable)。需要说明的是,当前线程一般是非UI线程,也可以是UI线程(如其它UI相关线程如awt UI 线程,和为提高执行效率,多个SWT UI线程之间协作并发执行,甚至调用线程和执行runnable 的UI线程是同一个线程)

syncExec与asyncExec不相同点体现在对方法调用线程本身的影响,syncExec阻塞当前线

程直到UI线程完成runnable中的代码执行;而asyncExec则直接返回,不等待runnable中代码被执行,但并不是说asyncExec执行的代码一定不在同一个线程中,有些时候是同一个线程,只不过将代码的执行根据需要分成两个部分或多个部分处理。

两者的异同决定了其分别适应不同的场合,一般syncExec适合在需要同步UI更新之后继续执行的代码,asyncExec适合在不便、不能syuncExec的情况下使用。

syncExec适用情况比较简单,以下总结asyncExec的适用情况。

1、非UI线程需要调用在UI线程中调用的组件方法。非UI线程是相对与UI线程来讲的,UI线程准确的讲是diaplay变量所在的线程,因此非UI线程其实是非display所在的线程,其可以是任何其它线程,如UI无关的后台作业处理线程、SWT-AWT共用应用中的awt所在线程、其它display线程(这种情况比较少,一般应用于服务程序,如大量生成图片的多UI 线程,相互之间协调时的调用,如几个UI线程负责地图图片的绘制,然后交给另外一个UI 线程做装饰处理);

2、跳出当前UI事件处理,安排后续事件。当前display所在的UI线程,在事件处理过程中,需要在执行完毕之后启动另外一个UI处理过程,可以使用asyncExec,发起另外一个UI线程处理,结束当前的UI处理。有几种情况下需要这么做:A、当前事件处理必须执行完毕,使应用到达一定的状态之后,做另外的UI处理,但是由于SWT、JFace或其它应用框架的存在,当前事件处理完成之后需要应用框架执行一些其它代码之后才可以执行另外的UI处理,否则会导致状态不一致,界面出错。但是当前事件处理完毕之后,不会出现其它事件来触发需要另外执行的代码,此时可以使用asyncExec,在框架的事件处理序列中插入另外一个事件,在当前事件处理完毕之后的某个时刻(一般很快)来执行;B、定时刷新或其它不是很重要的UI操作,通过asyncExec执行,不影响重要的UI事件处理。asyncExec所在的事件队列优先级较低。

3、事件比较密集,而且不均衡,有时非常密集,有时不太密集,为了将事件处理均衡处理,使UI线程始终能够应付自如,而不是延迟重要事件的处理、使用户感到界面迟钝现象,将不重要的事件放到低优先级序列中,从而保证用户响应性,界面整体的有效性。

asyncExec使用时需要注意的问题主要在于两个方面。

1、响应及时性。可以认为SWT存在两个事件队列,正常UI事件队列,需异步处理的队列,该队列优先级较低,asyncExec对应于SWT低优先级队列,因此有可能在正常队列事件较多、事件处理较慢的时候,asyncExec相关代码不能及时执行的问题,从而导致响应不够及时;

2、多线程同步问题。假如某段事件处理代码发出多个asyncExec请求,每个asyncExec

代码访问同一个变量,假设该变量是整数,第一次发出请求是值为1、第二次为2、第三次为3,所有请求发出,该事件处理完毕时,整数值为5,随后第一次发出的asyncExec请求执行,访问整数变量,此时为5,而本应该是1,其它几个有类似问题。

当然了,Display也提供了timerExec,可以将其理解为Timer和asyncExec两者的结合,代码在指定时间之后异步执行。

本文来自CSDN博客,转载请标明出处:

https://www.360docs.net/doc/5f9091548.html,/chulaixi/archive/2008/10/18/3095376.aspx

android studio 控件常用属性

android studio 控件常用属性 下面是RelativeLayout各个属性 1.android:layout_above="@id/xxx" --将控件置于给定ID控件之上 2.android:layout_below="@id/xxx" --将控件置于给定ID控件之下 3. android:layout_toLeftOf="@id/xxx" --将控件的右边缘和给定ID控件的左边缘对齐 4.android:layout_toRightOf="@id/xxx" --将控件的左边缘和给定ID控件的右边缘对齐 5. android:layout_alignLeft="@id/xxx" --将控件的左边缘和给定ID控件的左边缘对齐 6.android:layout_alignTop="@id/xxx" --将控件的上边缘和给定ID控件的上边缘对齐 7.android:layout_alignRight="@id/xxx" --将控件的右边缘和给定ID控件的右边缘对齐 8.android:layout_alignBottom="@id/xxx" --将控件的底边缘和给定ID控件的底边缘对齐 9.android:layout_alignParentLeft="true" --将控件的左边缘和父控件的左边缘对齐 10. android:layout_alignParentTop="true" --将控件的上边缘和父控件的上边缘对齐 11. android:layout_alignParentRight="true" --将控件的右边缘和父控件的右边缘对齐 12.android:layout_alignParentBottom="true" --将控件的底边缘和父控件的底边缘对齐 13.android:layout_centerInParent="true" --将控件置于父控件的中心位置 14.android:layout_centerHorizontal="true" --将控件置于水平方向的中心位置 15.android:layout_centerVertical="true" --将控件置于垂直方向的中心位置 android:layout_width 设置组件的宽度 android:layout_height 设置组件的高度 android:id 给组件定义一个id值,供后期使用 android:background 设置组件的背景颜色或背景图片 android:text 设置组件的显示文字 android:textColor 设置组件的显示文字的颜色 android:layout_below 组件在参考组件的下面 android:alignTop 同指定组件的顶平行

Android应用开发基础习题集

任务一 Android开发环境的搭建 第一部分知识回顾与思考 1.Android的四层架构分别包括哪几层分别起到什么作用 答:Linux内核层(Linux Kernel):基于Linux内核,内核为上层系统提供了系统服务。 系统库层(Libraries):系统库基于C/C++语言实现,通过接口向应用程序框架层提供编程接口。 应用框架层(Application Framework):为开发者提供了一系列的Java API,包括图形用户界面组件View、SQLite数据库相关的API、Service组件等。 应用程序层(Applications):包含了Android平台中各式各样的应用程序。 第二部分职业能力训练 一、单项选择题(下列答案中有一项是正确的,将正确答案填入括号内) 1.Android四层架构中,应用框架层使用的是什么语法( C ) A.C B.C++ C.Java D.Android 2.Android四层架构中,系统库层使用的是什么语法( B ) A.VB B.C /C++ C.Java D.Android 3.应用程序员编写的Android应用程序,主要是调用( B )提供的接口进行实现。 A.应用程序层 B.应用框架层 C.应用视图层 D.系统库层 二、填空题(请在括号内填空) 1.在Android智能终端中,有很多应用如拍照软件、联系人管理软件,它们都属于Android的(应用程序)层。 2.为了让程序员更加方便的运行调试程序,Android提供了(模拟器),可以方便的将程序运行其上,而不要实际的移动终端。 3.为了支持Java程序运行,我们需要安装(JDK)。 三、简答题 1.简述Android开发环境安装的步骤。 答:下载并安装JDK,配置JDK的环境变量; 从Anroid官网上下载Android开发组件(包含Eclipse和Android SDK、ADT); 安装Android开发环境(包括配置Android SDK的环境变量、打开Eclipse通过菜单设定Android SDK 路径)。 2.简述Android应用程序创建和运行的步骤。 答:通过菜单创建Android应用程序,设置应用程序名、Android版本等基本信息。

多线程技术在Android手机开发中的运用

龙源期刊网 https://www.360docs.net/doc/5f9091548.html, 多线程技术在Android手机开发中的运用 作者:谢光刘志惠 来源:《电子技术与软件工程》2017年第24期 摘要 在Android手机开发过程中,一般情况下程序是通过一个线程进行工作的,因此当一个任务耗费过长时间,就会造成主程序无响应并对程序运行的顺畅程度造成影响的问题。基于此,本文通过对多线程组成进行介绍,在Android中多线程技术模块与具体实现方式两方面对多线程技术在安卓手机开发中的运用进行探讨,以为关注此问题的人们提供参考。 【关键词】多线程技术 Android手机进程线程 安卓系统自2007年由谷歌公司开发后,得到了巨大的发展。截至2017年3月,其市场占有率已经达到86.4%,如三星、索尼爱立信、小米、OPPO等手机生产厂商都在使用安卓系统。该系统开源免费、执行效率高,其多线程技术开发应用的研究,对提高手机硬件的利用效率,给用户带来良好试用体验,提高手机厂商的企业竞争力有重要作用。 1 多线程介绍 1.1 进程和线程介绍 一般来说,在一定时间内实现多个程序任务执行的程序都会用到“进程”这一概念。进程,即:一个拥有自身独立的内存空间、系统资源的执行程序,其特征为实现内部状态和内部数据的相互独立。线程与进程相似,线程也是一段有一定功能代码组成的流控制。线程的特征为:同类的多个线程可以对内存空间与系统资源进行共享。因此在对资源的占用方面,可以相互切换的线程比进程小很多。一个进程中可以包含诸多线程,此外,主线程对子线程有控制作用,可对子线程启动、停止等动作进行管理。而本文要重点介绍的多线程,指的是单个程序中一起运行的不同线程,不同线程可以执行不一样的任务。其特征是一个程序的多行语句可在某时间同时执行。 1.2 多线程程序消息处理原理 当人们启动一个程序时,系统将建立main线程,主要管理如:activity等应用组件,并对UI相关的事件进行处理,比如用户想要按键或使用屏幕进行绘图,线程会对以上事件进行处理,这是UI线程。安卓的线程模型,所有组件均在main线程中,因此用户在程序中下达下载文件、使用数据库等具有高耗时特征的操作时,就会造成UI线程的运行不畅,并出现程序无法响应的问题。这就要求程序员使用多线程技术,在进行安卓多线程编写时,技术人员应注意以下两点:

Android常用控件

《Android基础应用》 Android常用控件 ?本章任务 ?使用Android开发使用时间组件 ?使用Android开发使用进度条组件 ?使用Android开发创建底部选项卡 ?本章目标 ?了解Android的组件层次结构 ?掌握常用的日期时间类控件 ?掌握常用的几个容器组件 1.Android组件的层次结构 UI组件都是View的子类,View有很多子类,它们之间存在树状的继承关系View及其子类结构图

TextView及其子类结构图

ViewGroup及其子类结构图 其下的子类一般作为容器或布局来使用 FrameLayout及其子类结构图 其下的子类通常作为容器或布局来使用

2.时间控件 2.1日期时间选择器 DatePicker组件可用于输入日期,TimePicker组件可用来选择时间,只能输入小时和分,默认12小时制 DatePicker ●使用onDateChangedListener监听器来获取用户的日期选择 ●使用init对组件进行初始化 ●使用getYear,getMonth,getDayOfMonth方法获得用户选择的年,月,日 TimePicker ●使用onTimeChangedListener监听器获取用户的时间选择 ●使用setIs24HourView设置是否以24小时制显示 ●使用getCurrentHour获得当前的小时数 ●使用getCurrentMinute获得当前的分钟数 示例

示例的实现结果

2.2时钟组件 AnalogClock组件用来以表盘的方式显示当前时间,该表只有时针和分针,DigitClock组件以数字的方式显示当前时间可以显示时分秒,由于DigitClock继承TextView,可以使用TextView 的属性 示例

Android下使用Http协议实现多线程断点续传下载

0.使用多线程下载会提升文件下载的速度,那么多线程下载文件的过程是: (1)首先获得下载文件的长度,然后设置本地文件的长度 HttpURLConnection.getContentLength(); RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd"); file.setLength(filesize);//设置本地文件的长度 (2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。 如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示。 例如10M大小,使用3个线程来下载, 线程下载的数据长度 (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M 下载开始位置:线程id*每条线程下载的数据长度 = ? 下载结束位置:(线程id+1)*每条线程下载的数据长度-1=? (3)使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止, 如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止 代码如下:HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303"); (4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。 RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd"); threadfile.seek(2097152);//从文件的什么位置开始写入数据

android常用控件大全

android常用控件大全 在Android中使用各种控件(View) DatePicker-日期选择控件 TimePicker-时间选择控件 ToggleButton-双状态按钮控件 EditText-可编辑文本控件 ProgressBar-进度条控件 SeekBar-可拖动的进度条控件 AutoCompleteTextView-支持自动完成功能的可编辑文本控件 MultiAutoCompleteTextView-支持自动完成功能的可编辑文本控件,允许输入多值(多值之间会自动地用指定的分隔符分开) ZoomControls-放大/缩小按钮控件 Include-整合控件 VideoView-视频播放控件 WebView-浏览器控件 RatingBar-评分控件 Tab-选项卡控件 Spinner-下拉框控件 Chronometer-计时器控件 ScrollView-滚动条控件 在Android中使用的Layout FrameLayout:里面只可以有一个控件,并且不能设计这个控件的位置,控件会放到左上角 LinearLayout:里面可以放多个控件,但是一行只能放一个控件

TableLayout:这个要和TableRow配合使用,很像html里面的table AbsoluteLayout:里面可以放多个控件,并且可以自己定义控件的x,y的位置 RelativeLayout:里面可以放多个控件,不过控件的位置都是相对位置 (Android界面布局好像还可以直接引用一些view,如ScrollView等) 常用控件: 1,EditText 主要函数:setText/getText设置/获取文本内容,setHint设置缺省显示内容; 2,RadioGroup,RadioButton RadioButton的isChecked()判断是否被选中 获取选中RadioButon的ID:设置 RadioGroup.setOnCheckedChangeListener方法 publiconCheckedChanged(RadioGroupgroup,intcheckedId)//checkedId 是选中RadioButton的ID 3,CheckBox isChecked()判断是否被选中 setOnCheckedChangeListener方法监视选中状态改变情况 4,Spinner a,显示数据 1),硬编码加载 通过setAdapter方法设置类型为 ArrayAdapter(Contextcontext,inttextViewResId,String[]objects) textViewResourceId:显示内容的ViewID默认设置为 https://www.360docs.net/doc/5f9091548.html,yout.simple_spinner_item

AndroidUI之线程与进度对话框

//创建一个进度条对话框 final ProgressDialog progressdialog=new ProgressDialog(MainActivity.this); progressdialog.setTitle("测试"); progressdialog.setMessage("正在对话框与线程"); progressdialog.show();//显示对话框 //创建线程 new Thread(){ public void run(){ try{ sleep(1000);//时间间隔1秒 }catch(Exception e){ e.printStackTrace(); }finally{ progressdialog.dismiss();//卸载对话框对象 } } }.start(); 菜单的创建于事件监听 public boolean onCreateOptionsMenu(Menu menu) { int a=Menu.NONE;//声明菜单顺序ID int b=Menu.NONE+1; int c=Menu.NONE+2; int d=Menu.NONE+3; menu.add(0, 1, a, "a");//第一个参数:分组,第二个参数:菜单的Id, 第三个参数:菜单的顺序,第四个参数:显示菜单的文字 menu.add(1, 2, b, "b"); menu.add(2, 3, b, "c"); menu.add(2, 4, d, "d"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case 1: Toast.makeText(MainActivity.this,"a", 1).show(); break; case 2: Toast.makeText(MainActivity.this,"b", 1).show(); break;

Android应用开发基础习题

-- 任务一Android 开发环境的搭建 第一部分知识回顾与思考 1.Android 的四层架构分别包括哪几层?分别起到什么作用? 答:Linux 内核层(Linux Kernel ):基于Linux 内核,内核为上层系统提供了系统服务。 系统库层(Libraries ):系统库基于C/C++ 语言实现,通过接口向应用程序框架层提供编程接口。 应用框架层(Application Framework ):为开发者提供了一系列的Java API,包括图形用户界面组件

View 、SQLite 数据库相关的API 、Service 组件等。 应用程序层(Applications ):包含了Android 平台中各式各样的应用程序。 第二部分职业能力训练 一、单项选择题(下列答案中有一项是正确的,将正确答案填入括号内) 1.Android 四层架构中,应用框架层使用的是什么语法?(C)A .CB .C++C.Java D.Android 2.Android 四层架构中,系统库层使用的是什么语法?(B)A .VBB.C /C++C.Java D .Android 3.应用程序员编写的Android 应用程序,主要是调用(B)提供的接口进行实现。 A .应用程序层DCB.应用框架层.应用视图层.系统库层

二、填空题(请在括号内填空) 1.在Android 智能终端中,有很多应用如拍照软件、联系人管理软件,它们都属于Android 的(应用程 序)层。 2.为了让程序员更加方便的运行调试程序,Android 提供了(模拟器),可以方便的将程序运行其上, 而不要实际的移动终端。 程序运行,我们需要安装(Java 3.为了支持)。JDK 三、简答题 1.简述Android 开发环境安装的步骤。 答:下载并安装JDK ,配置JDK 的环境变量; 从Anroid 官网上下载Android 开发组件(包含Eclipse 和

Android Handle Thread

有关Android线程的学习 1. Android进程 会尽量保留一个正在运行进程,只在内存资源出现不足时,Android会尝试停止一些进程从而释放足够的资源给其他新的进程使用,也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。按照重要性从高到低一共有五个级别: ?前台进程 前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。一般来说,在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。 ?可见进程 可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。 ?服务进程 运行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。 ?后台进程 运行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。 ?空进程 未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。

实验二 android基本控件实验

实验二 android基本控件实验 【目的】 熟悉Android常用控件的基本操作,掌握它们的基本使用方法。了解控件之间的构成关系,熟悉适配器的使用原理。 【要求】 1、了解控件的继承关系; 2、掌握适配器的使用; 3、掌握信息提示的实现机制; 4、实现基本界面。 【原理】 1.控件类之间的关系 android.view.View类(视图类)呈现了最基本的UI构造块。View类是Android中的一个超类,几乎包含了所有的屏幕类型,主要负责绘制和事件处理。 Android中控件类的扩展结构如图所示。 View有众多的扩展者,它们大部分是在android.widget包中,这些继承者实际上就是Android 系统中的“控件”。View实际上就是各个控件的基类,创建交互式的图形用户界面的基础。View的直接继承者包括文本视图(TextView)、图像视图(ImageView)、进度条(ProgressBar)等。它们各自又有众多的继承者。每个控件除了继承父类功能之外,一般还具有自己的公有 方法、保护方法、XML属性等。 在Android中使用各种控件的一般情况是在布局文件中可以实现UI的外观,然后在Java文件中实现对各种控件的控制动作。控件类的名称也是它们在布局文件XML中使用的标签名称。

2.控件通用行为和属性 View是Android中所有控件类的基类,因此View中一些内容是所有控件类都具有的通用行为和属性。 提示:由于Java语言不支持多重继承,因此Android控件不可能以基本功能的“排列组合”的方式实现。在这种情况下,为了实现功能的复用,基类的功能往往做得较强,作为控件的祖先类,View所实现的功能也是最多的。 控件类经常在布局文件中使用,因此其可以使用XML属性(XMLAttributes),和Java代码经常具有对应关系。 View作为各种控件的基类,其XML属性所有控件通用,XML属性及其对应的方法如表1所示。 表1 View中的XML属性及其对应的方法 其中,android:id表示控件的标识,通常需要在布局文件中指定这个属性。View中与控件标识相关的几个方法如下所示: public int getId() // 获得控件的id(int类型)

Android应用程序开发完整训练:从零起步通过23个动手实战案例精通App开发

从零起步,24小时内通过23个动手实战案例,循序渐进的对Android商业级别的应用程序开发要点各个击破,依托于在多年的Android(6款完整的硬件产品和超过20款应用软件)开发和企业级培训经验(超过150期的次Android的企业内训和公开课),旨在在实务的基础之上帮助你完成任何复杂程序的高质量Android应用程序开发,让Android开发跟上想象的速度。最后,通过ActivityManagerService揭秘Android应用程序一切行为背后的核心根源,让你从此开发应用程序居高零下、举重若轻。 课程要点: 1,抽取Android应用开发中用到的最精华的Java技术加以剖析; 2,从零起步构建Android开发环境和编写并彻底剖析第一个Android程序; 3,彻底剖析不同Activity之间所有的交互模式; 4,根据商业化场景彻底剖析Android的生命周期及其使用的最佳时间; 5,使用JUnit测试Android业务代码; 6,掌握Android基本和核心的UI开发技术; 7,”Android商业化高级UI实战”是根据过去20多款商业级别Android应用程序开发尤其是类似CRM系统中最经典、最经常使用的技术抽取而成,掌握之后基本上不会在遇到UI 方面的难点; 8,细致剖析并实战Android性能测试,找出性能瓶颈,并进行代码优化,分享代码优化的最佳实践; 9,对数据的处理时Android绝大多数应用程序的核心,尤其是对CRM系统而言,这一天,我们会对Android中的本地数据处理方式及其商业使用场景进行彻底剖析和实战; 10,从SharedPreferences到内部文件系统,从SDCard操作到SQLite数据库,从XML 和JSON的解析于生成到数据共享统一接口ContentProvider,对Android本地的数据处理方式进行地毯式轰炸; 11,通讯录的操作的原理、流程和场景等进行了情景再现性的代码实战; 12,通过Android手机卫士商业级别的代码案例实战Android中BroadcastReceiver和Service; 13,根据过去20多款程序的商业实战总结出了能够解决基于HTTP协议的任意文件类型、任意大小文件的网络上传和下载,Android网络开发从此一劳永逸; 14,实战WiFi数据交换; 15,尤其是额外提到异步http框架,具备很强的商业价值; 16,Android横竖屏切换的经典场景、生命周期和解决方案; 17,实战构建多语言国际化的Android应用程序; 18,如何编译APK来提高应用的安全性; 19,如何反编译Android应用 20,通过Android中WebView的特性洞悉Android中JavaScript与Java相互沟通的密码,追寻浏览器和HTML5开发的架构和技术实现根源; 21,使用NDK等技术利用C/C++的高效性来提高应用程序的性能; 22,实现Android中以Looper、Handler、Message、MessageQueue为核心的线程间通信方式; 23,实战并剖析AsyncTask框架实现的源代码,并提出对AsyncTask缺陷的解决方案;

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中嵌入一个Button 2. 点击Button, 运行一个耗时很长的操作, 反复修改Button的文字, 在该线程中打印该线程的名称 代码是这样的: 1.public static void 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. https://www.360docs.net/doc/5f9091548.html,yout(); 12.while (!shell.isDisposed()) { 13.if (!display.readAndDispatch()) 14. display.sleep(); 15. } 16. shell.dispose(); 17. display.dispose(); 18.} 19.private static void registerAction() { 20. btn.addMouseListener(new MouseListener() { 21. @Override 22.public void mouseDoubleClick(MouseEvent e) { 23. // TODO Auto-generated method stub 24. } 25. @Override 26.public void mouseDown(MouseEvent e) { 27. methodA(); 28. } 29. @Override 30.public void mouseUp(MouseEvent e) { 31. } 32. }); 33.} 34./**

Android复习题

Android复习题及答案 一、选择题 1. 下列哪些语句关于内存回收的说明是正确的?( ) A、程序员必须创建一个线程来释放内存 B、内存回收程序负责释放无用内存 C、内存回收程序允许程序员直接释放内存 D、内存回收程序可以在指定的时间释放内存对象 2. Android 中下列属于Intent的作用的是( ) A、实现应用程序间的数据共享 B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失 C、可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带 D、处理一个应用程序整体性的工作 3. 下面的对自定style的方式正确的是( ) A、 B、 C、 fill_parent D、 fill_parent 4. 在Android中使用Menu时可能需要重写的方法有( )。 A、onCreateOptionsMenu() B、onCreateMenu() C、onOptionsItemSelected() D、onItemSelected() 5. 在Android中使用SQLiteOpenHelper这个辅助类时,可以生成一个数据库,并可以对数据库 版本进行管理的方法可以是( )

Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask等

方法一:(java习惯,在android不推荐使用) 刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题new Thread( new Runnable() { public void run() { myView.invalidate(); } }).start(); 可以实现功能,刷新UI界面。但是这样是不行的,因为它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。 方法二:(Thread+Handler) 查阅了文档和apidemo后,发觉常用的方法是利用Handler来实现UI线程的更新的。Handler来根据接收的消息,处理UI更新。Thread线程发出Handler消息,通知更新UI。Handler myHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case TestHandler.GUIUPDATEIDENTIFIER: myBounceView.invalidate(); break; } super.handleMessage(msg); } }; class myThread implements Runnable { public void run() { while (!Thread.currentThread().isInterrupted()) { Message message = new Message(); message.what = TestHandler.GUIUPDATEIDENTIFIER; TestHandler.this.myHandler.sendMessage(message); try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } 以上方法demo看:https://www.360docs.net/doc/5f9091548.html,/blog/411860 方法三:(java习惯,不推荐) 在Android平台中需要反复按周期执行方法可以使用Java上自带的TimerTask类, Tim erTask相对于Thread来说对于资源消耗的更低,除了使用Android自带的

android多线程下载技术详解

Android 多线程、断点续传下载技术 1.为什么使用该技术? 答:(1)之所以采用多线程下载是因为考虑到手机,及移动设备的cup处理能力,让下载任务多抢占cup资源,从而加快了下载的速度,提高了用户体验 (2)断点续传技术,就是在下载过程中如果网络出现问题,导致文件没有下载完,那么下次下载时,接着上次终端位置继续下载,从而减轻了服务器的负担。 2.下面我们就开始建一个多线程下载的项目,来体验多线程下载的优势,项目的结构如下 2.1设计UI

main.xml 代码如下:

android:text="@string/path" />

相关文档
最新文档