首页编程java编程java的handler是什么意思?java 中为什么要引入handler这种设计方法

java的handler是什么意思?java 中为什么要引入handler这种设计方法

编程之家 2023-10-10 104次浏览

大家好,如果您还对java的handler是什么意思不太了解,没有关系,今天就由本站为大家分享java的handler是什么意思的知识,包括java 中为什么要引入handler这种设计方法的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

java的handler是什么意思?java 中为什么要引入handler这种设计方法

在c#程序设计里 Handler 这个词一般会翻译成什么

这个怎么翻译,应该不重要吧...

...

晓得意思,怎么用就可以了呀...

java的handler是什么意思?java 中为什么要引入handler这种设计方法

..

这个一般是在

KeyPress事件中的参数

java的handler是什么意思?java 中为什么要引入handler这种设计方法

KeyPressEventArgs

e

所具有的参数,e.Handler

可以将它的值设为

true或false

当e.Handler=true的时候,就是阻止用户输入,为false就是允许用户输入。要是硬要翻译的话,可以把他联系事件翻译成:输入事件的控制者吧...

...

Android中Handler的使用方法

Handler在Android中主要是负责发送和处理消息。它的主要用途大致是下面两个:

1)按计划发送消息或执行某个Runnanble;

2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程)

学写一下,在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理。在实例化Handler的时候,只要有Handler的指针,任何线程也都可以sendMessage。

Handler对于Message的处理是异步处理的。一个Looper只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)。

根据对视频的学习写了一个通过Button控件启动进度条(类似于下载等操作)的程序,简单介绍一下,有两个Button控件,一个是开始,点击之后会显示一个进度条以每次十分之一的进度进行(一开始是隐藏的),另一个是停止,可以中断进度。

java代码:

1 package zzl.handleactivity;

2

3 import android.app.Activity;

4 import android.os.Bundle;

5 import android.os.Handler;

6 import android.os.Message;

7 import android.view.Gravity;

8 import android.view.View;

9 import android.view.View.OnClickListener;

10 import android.widget.Button;

11 import android.widget.ProgressBar;

12 import android.widget.Toast;

13

14 public class Handler_01 extends Activity{

15

16//声明变量

17 private Button startButton=null;

18 private Button endButton=null;

19 private ProgressBar firstBar=null;

20 private Toast toast=null;

21@Override

22 protected void onCreate(Bundle savedInstanceState){

23 super.onCreate(savedInstanceState);

24 setContentView(R.layout.main);

25

26//根据ID获取对象

27 startButton=(Button)findViewById(R.id.startButton);

28 endButton=(Button)findViewById(R.id.endButton);

29 firstBar=(ProgressBar)findViewById(R.id.firstBar);

30//给对象设置动作监听器

31 startButton.setOnClickListener(new StartButtonListener());

32 endButton.setOnClickListener(new EndButtonListener());

33}

34

35 class StartButtonListener implements OnClickListener{

36

37@Override

38 public void onClick(View v){

39// TODO Auto-generated method stub

40//一开始执行,加入到消息队列,不延迟,

41//然后马上执行run方法

42 firstBar.setVisibility(View.VISIBLE);

43 firstBar.setMax(100);

44 handler.post(upRunnable);

45 toast=Toast.makeText(Handler_01.this,"运行开始", Toast.LENGTH_SHORT);

46 toast.setGravity(Gravity.CENTER, 0, 0);

47 toast.show();

48}

49}

50 class EndButtonListener implements OnClickListener{

51

52@Override

53 public void onClick(View v){

54// TODO Auto-generated method stub

55//停止

56 handler.removeCallbacks(upRunnable);

57 System.out.println("It's time to stop...");

58}

59}

60

61//创建handler对象,在调用post方法

62//异步消息处理:将下载或者处理大数据等等单独放到另一个线程

63//更好的用户体验

64 Handler handler=new Handler(){

65

66@Override

67 public void handleMessage(Message msg){

68 firstBar.setProgress(msg.arg1);

69 firstBar.setSecondaryProgress(msg.arg1+10);

70//handler.post(upRunnable);

71 if(msg.arg1<=100){

72 handler.post(upRunnable);//将要执行的线程放入到队列当中

73}else{

74 handler.removeCallbacks(upRunnable);

75}

76}

77};

78

79//声明线程类:实现Runnable的接口

80 Runnable upRunnable=new Runnable(){

81

82 int i=0;

83@Override

84 public void run(){//程序的运行状态

85// TODO Auto-generated method stub

86//postDelayed方法:把线程对象加入到消息队列中

87//隔2000ms(延迟)

88 System.out.println("It's time to start...");

89 i=i+10;

90//获取Message消息对象

91 Message msg=handler.obtainMessage();

92//将msg对象的arg1(还有arg2)对象的值设置

93//使用这两个变量传递消息优点:系统消耗性能较少

94 msg.arg1=i;

95 try{

96//设置当前显示睡眠1秒

97 Thread.sleep(1000);

98}catch(InterruptedException e){

99 e.printStackTrace();

100}

101//将msg对象加入到消息队列当中

102 handler.sendMessage(msg);

103 if(i==100){//当值满足时,将线程对象从handle中剔除

104 handler.removeCallbacks(upRunnable);

105 firstBar.setVisibility(View.GONE);

106//临时弹出

107

108 toast=Toast.makeText(Handler_01.this,"运行结束", Toast.LENGTH_SHORT);

109 toast.setGravity(Gravity.CENTER, 0, 0);

110 toast.show();

111}

112}

113};

114}

main.xml

1<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

2 xmlns:tools="http://schemas.android.com/tools"

3 android:orientation="vertical"

4 android:layout_width="match_parent"

5 android:layout_height="match_parent"

6 tools:context=".Handler_01">

7

8<ProgressBar

9 android:id="@+id/firstBar"

10 style="?android:attr/progressBarStyleHorizontal"

11 android:layout_width="200dp"

12 android:layout_height="wrap_content"

13 android:visibility="gone"/>

14

15<Button

16 android:id="@+id/startButton"

17 android:layout_width="wrap_content"

18 android:layout_height="wrap_content"

19 android:text="@string/start"/>

20

21<Button

22 android:id="@+id/endButton"

23 android:layout_width="wrap_content"

24 android:layout_height="wrap_content"

25 android:text="@string/end"/>

26

27</LinearLayout>

总结:

1)当点击开始或者运行结束的时候,都会通过调用Toas弹出临时窗口,Toast.makeText(Handler_01.this,"运行结束", Toast.LENGTH_SHORT),这一句一开始总是执行出错,原因在于必须调用它的show方法才可以显示出来,还可以通过设置它的位置来显示;

2)在xml中 android:text="@string/end",则需要在layout下的string文件中敲写相应的代码

3)原本代码有一些瑕疵,就是没有下面这一段代码:

1 if(msg.arg1<=100){

2 handler.post(upRunnable);//将要执行的线程放入到队列当中

3}else{

4 handler.removeCallbacks(upRunnable);

5}

这样就导致了upRunnable的run方法出现了死循环,这样,虽然程序UI本身没有问题,但是内部却又很大的缺陷

这是因为

1 if(i==100){//当值满足时,将线程对象从handle中剔除

2 handler.removeCallbacks(upRunnable);

3 firstBar.setVisibility(View.GONE);

4 toast=Toast.makeText(Handler_01.this,"运行结束", Toast.LENGTH_SHORT);

5 toast.setGravity(Gravity.CENTER, 0, 0);

6 toast.show();

7}

这一段代码看似是把upRunnable线程从线程对象队列中移除,但是再次之前又前执行了handler.sendMessage(msg);这句代码

从而导致下面的代码又被执行到

1 public void handleMessage(Message msg){

2 firstBar.setProgress(msg.arg1);

3 firstBar.setSecondaryProgress(msg.arg1+10);

4

5}

这样肯定会使upRunnable线程重新加入到线程对象队列中,updateThread的run方法重复执行,这就导致了死循环。所以必须加上之前的那段代码,通过判断来控制循环终止。并且run方法中的if(i==100)的那段代码也是可以不用的,不过我是写了一些其他代码就懒得优化了,这是后话了。

4)刚刚大家看到我们可以通过敲写System.out.println在logcat中显示,一开始eclipse编译器中是没有,这是如何显示出来的?

大家可以再window的show view中找到logCat(deprecated)通过下图中绿色的“+”添加出来

然后显示内容的时候,选择右上角“V D I W E”的I就可以比较清晰的显示出来了,当然你也可以选择另外一个logCat来显示,方法类似。

5)实际上,Handler在默认情况下,和调用它的Activity是处于同一个线程的。上述Handler的使用示例中,虽然声明了线程对象,但是在实际调用当中它并没有调用线程的start()方法,而是直接调用当前线程的run()方法。

如果要实现调用另一个新的线程,只要注释post方法,然后加上这样两段代码即可: Thread t= new Thread(r); t.start();

Python中的logger和handler到底是个什么鬼

最近的任务经常涉及到日志的记录,特意去又学了一遍logging的记录方法。跟java一样,python的日志记录也是比较繁琐的一件事,在写一条记录之前,要写好多东西。典型的日志记录的步骤是这样的:

创建logger

创建handler

定义formatter

给handler添加formatter

给logger添加handler

写成代码差不多就是酱婶的(这个是照别的网页抄的,参考附注):

1 import logging

2 3# 1、创建一个logger 4 logger= logging.getLogger('mylogger')

5 logger.setLevel(logging.DEBUG)

6 7# 2、创建一个handler,用于写入日志文件 8 fh= logging.FileHandler('test.log')

9 fh.setLevel(logging.DEBUG)

10 11#再创建一个handler,用于输出到控制台 12 ch= logging.StreamHandler()

13 ch.setLevel(logging.DEBUG)

14 15# 3、定义handler的输出格式(formatter)16 formatter= logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')

17 18# 4、给handler添加formatter19 fh.setFormatter(formatter)

20 ch.setFormatter(formatter)

21 22# 5、给logger添加handler 23 logger.addHandler(fh)

24 logger.addHandler(ch)

之后才可以正式的开始记录日志。Java里面的java.util.Logging类差不多也是这样,代码还要更复杂一点。Golang的日志相对写法简单一些,不过没有什么格式,系统记录一条时间,内容格式完全自己手画。第三方的日志库倒是没有接触过,像Java的Log4j,Golang的log4go和seelog等等,不知道用起来会不会简单一点。我一直都记不住这些,因为不太理解logger和handler为什么要这样写。一直到这次任务中出现的在我看来相当“诡异”的bug,才深入理解了一下。

我的任务是这样的,要做一个日志切割的工具,按天将日志分割开,即每天0点产生一个新日志,将旧日志改名。并且,将超过3个月的日志删除掉,以保证磁盘空间不会被log占满。程序要求可以切割多个目录中的不同日志,具体路径由json中配置。

这里用到了logging.handlers类中的TimedRotatingFileHandler方法,用以获得一个handler。大概的写法为:

1 logger= logging.getLogger()#获得logger2 handler= logging.handlers.TimedRotatingFileHandler(logfile,'S', 1, 0)#切割日志3 handler.suffix='%Y%m%d'#切割后的日志设置后缀4 logger.addHandler(handler)#把logger添加上handler5 logger.fatal(datetime.datetime.now().strftime('%Y-%m-%d'))#在新日志中写上当天的日期

这里我没有设置level和formatter。因为只是分割,对新日志没有什么影响。TimedRotatingFileHandler函数的方法见附注,或查看python的源码,这个函数是python写的,可以找到定义。这里我使用的是每秒生成一个新的日志文件,之后用Crontab在每天0点调度,然后用for循环处理json中的每一个日志文件。

但是奇怪的是,每次运行程序,第一个切割的日志生成一个分割后的文件,而后面的都生成两个新日志。百思不得其解。后检查代码觉得,可能是程序中设置的时间太短了,每秒生成一个文件,有可能一秒钟处理不完,就生成了两个。虽然这个说法没有什么科学根据,但是还是把TimedRotatingFileHandler中的第三个参数改成了60,即每60秒生成一个文件。完成,静静的等待crontab到时间。

叮!时间到。赶紧检查一下结果。一个好消息和一个坏消息。好消息是这次每个日志都只切割生成了一个新文件,没有生成两个。坏消息是每个文件里面添加的当天的日期的数量见鬼了。我切割了4条日志,生成的新日志里面就分别写上了一、二、三、四行当天日期。

此刻我的内心几乎是崩溃的。我开始思考为什么会这样。很明显四行日期是调用了4次logger.fatal('datetime.datetime.now().strftime('%Y-%m-%d'))这个函数。换句话说,我每一次for循环都在这个log里面写了一句话。可是明明每个for是处理一个日志,下一次for应该是处理下一个日志的,为什么会再处理这个日志一次?我突然想到,logger.addHandler(handler)是每次循环都会运行的,也就是说,logger是同一个logger,添加了4次handler。到第4次循环的时候,这个logger中有4个handler,也就会往4个不同的日志中添加内容了。呃。

如果是这样的话,那么把上面的程序改改,第一句和最后一句放在循环外,循环内只用中间的三句。这次OK了。回头再看log记录的步骤,也就明白了logger和handler到底是个什么鬼:logger可以看做是一个记录日志的人,对于记录的每个日志,他需要有一套规则,比如记录的格式(formatter),等级(level)等等,这个规则就是handler。使用logger.addHandler(handler)添加多个规则,就可以让一个logger记录多个日志。至于logging.getLogger()方法获得的root logger和继承关系,可以详见附注的网页,这里我也只是大概明白了什么意思,还没有具体用过。也许将来在框架中使用,要记录较为复杂的日志时候会用到吧。

java 中为什么要引入handler这种设计方法

代码的目的是满足需求,操作方便自然就写了,无论handler还是controller,都是为了实现需求,但当出现大量handler的时候,说明这个程序员啥都不懂,连命名都不会了,命名成XXService、XXDao等,至少从代码上可以看出层次看出功能,便于后期维护

如果这是项目经理写的,只能说明他画虎不成反类犬,很不可取,千万别跟他学

好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!

java什么接口测试工具(接口自动化测试工具有哪些) java中为什么要引入构造器,Java中构造器有什么用