Button.setOnClickListener(OnClickListener l) 原理

本文介绍如何通过继承EditText来自定义文本框,并实现文本变化时的监听功能。通过定义OnTextChangedListener接口及TextWatcher对象,可以实现在文本内容发生改变时执行特定的回调函数。

android,java使用Button 可能都会监听之 当其被点击 就会有函数负责回调 那么其到底是怎么实现的呢?

今天要做的就是摸清楚之 为了减少不必要的麻烦 打算extends EditText 并在其上设立监听器


[代码 步骤]

1. 定义Edit2Text 且extends EditText


  1. public class Edit2Text extends EditText {  
  2. OnTextChangedListener changedListener;  

  3. TextWatcher tWatcher;  
  4. }  
复制代码

2. 定义其上的监听器:OnTextChangedListener 并定义函数:onChanged() 用于执行具体回调

  1. public static interface OnTextChangedListener {  
  2. public void onChanged(Edit2Text e2t, String text);  

  3. }  
复制代码
  1. 需要注意的 这几行代码的修饰关键字:  

  2. 1. static :使其能够脱离Edit2Text而存在  

  3. 2. interface : 使其自动填充其内部函数  

  4. 3. “void onChanged(Edit2Text e2t, String text)” 中的第一个参数e2t 用于做分别 具体奥妙 后面再细说  
复制代码
3.  设定监听器
  1. public void setOnChangedListener(OnTextChangedListener l){  
  2. changedListener = l;  
  3. }  
复制代码

4. 定义TextWatcher 当字符内容改变 通知监听器

* 定义TextWatcher'

  1. tWatcher = new TextWatcher(){  
  2.            @Override  
  3.             public void afterTextChanged(Editable s) {  
  4.               // TODO Auto-generated method stub  
  5. 06.                   
  6.            }  

  7.             @Override  
  8.             public void beforeTextChanged(CharSequence s, int start, int count,  
  9.                    int after) {  
  10.             // TODO Auto-generated method stub  
  11.                
  12.           }  

  13.             @Override  
  14.           public void onTextChanged(CharSequence s, int start, int before,  
  15.                 int count) {  
  16.                // TODO Auto-generated method stub  
  17.               updateText(s.toString());  
  18.              }  
  19.              
  20.        };  
  21.           
  22.   this.addTextChangedListener(tWatcher);  
复制代码
* 通知监听器
  1. private void updateText(String s){  
  2. changedListener.onChanged(this, s);  

复制代码
5. 如何使用
  1. public class Edit2TextTest extends Activity {  
  2.      /** Called when the activity is first created. */  
  3. @Override  
  4.    public void onCreate(Bundle savedInstanceState) {  
  5.          super.onCreate(savedInstanceState);  
  6. 06.         setContentView(R.layout.main);         
  7.        Edit2Text e2t = new Edit2Text(this);  
  8.         setContentView(e2t);  
  9.            
  10.         e2t.setOnChangedListener(new Edit2Text.OnTextChangedListener(){     
  11.             @Override  
  12.            public void onChanged(Edit2Text e2t, String text) {  
  13.                // TODO Auto-generated method stub  
  14.                Log.d("TAG","[String:]"+text);  
  15.             }  
  16. });  
  17.      }  

复制代码
* Log 信息:

  1. Java代码  收藏代码
  2. 01. D/dalvikvm(  674): GC freed 223 objects / 8848 bytes in 108m  
  3. 02. D/TAG     (  941): [String:]i am  
  4. 03. D/TAG     (  941): [String:]i am  
  5. 04. D/TAG     (  941): [String:]i am e  
  6. 05. D/TAG     (  941): [String:]i am ed  
  7. 06. D/TAG     (  941): [String:]i am edi  
  8. 07. D/TAG     (  941): [String:]i am edit  
  9. 08. D/TAG     (  941): [String:]i am edit2  
  10. 09. D/TAG     (  941): [String:]i am edit2t  
  11. 10. D/TAG     (  941): [String:]i am edit2te  
  12. 11. D/TAG     (  941): [String:]i am edit2tex  
  13. 12. D/TAG     (  941): [String:]i am edit2text  
  14. 13. D/TAG     (  941): [String:]i am edit2text,  
  15. 14. D/TAG     (  941): [String:]i am edit2text,  
  16. 15. D/TAG     (  941): [String:]i am edit2text, h  
  17. 16. D/TAG     (  941): [String:]i am edit2text, he  
  18. 17. D/TAG     (  941): [String:]i am edit2text, hel  
  19. 18. D/TAG     (  941): [String:]i am edit2text, hell  
  20. 19. D/TAG     (  941): [String:]i am edit2text, hello  
  21. 20. D/TAG     (  941): [String:]i am edit2text, hello!  
Android 开发中,调用 `Button.setOnClickListener()` 时出现空对象引用错误(`NullPointerException`),通常是因为尝试对一个为 `null` 的 `Button` 实例调用该方法。此类问题在实际开发中较为常见,尤其是在视图初始化过程中存在疏漏或逻辑错误时。 ### 原因分析 1. **未正确初始化视图**:在调用 `findViewById()` 时,若传入的 ID 与当前布局文件中定义的 ID 不匹配,或者未调用 `setContentView()` 设置布局,将导致 `Button` 对象为 `null`。例如: ```java Button button = (Button) findViewById(R.id.button_send); button.setOnClickListener(this); // 若 button 为 null,则抛出 NullPointerException ``` 此错误通常在 `setContentView()` 被遗漏或调用顺序错误时发生。例如,必须在 `onCreate()` 中先调用 `super.onCreate(savedInstanceState)`,然后调用 `setContentView()`,否则可能导致视图无法正确绑定 [^2]。 2. **XML 布局中未定义对应 ID**:若在 `res/layout/` 中的布局文件未定义 `R.id.button_send`,则 `findViewById()` 返回 `null`,后续调用 `setOnClickListener()` 时将引发空指针异常 [^2]。 3. **拼写错误或资源冲突**:ID 拼写错误、使用了错误的命名空间或资源冲突也可能导致 `findViewById()` 返回 `null`。 ### 解决方案 1. **确保调用顺序正确**:在 `Activity` 的 `onCreate()` 方法中,必须按照以下顺序执行: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 必须在 super.onCreate() 之后调用 Button button = (Button) findViewById(R.id.button_send); button.setOnClickListener(this); } ``` 若调换 `setContentView()` 和 `super.onCreate()` 的顺序,可能导致视图无法正确绑定 [^2]。 2. **检查 XML 布局文件中的 ID 定义**:确保 `R.id.button_send` 在 `activity_main.xml` 中正确定义: ```xml <Button android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" /> ``` 3. **使用非空判断避免崩溃**:在调用 `setOnClickListener()` 前,添加非空判断以避免程序崩溃: ```java Button button = (Button) findViewById(R.id.button_send); if (button != null) { button.setOnClickListener(this); } ``` 4. **使用 Lambda 表达式简化代码**(适用于 Java 8 及以上): ```java Button button = findViewById(R.id.button_send); if (button != null) { button.setOnClickListener(v -> { // 处理点击事件 }); } ``` 5. **通过 XML 中的 `android:onClick` 属性绑定方法**:在布局文件中直接指定点击事件方法名,避免手动设置监听器: ```xml <Button android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" android:onClick="onButtonClick" /> ``` 然后在 `Activity` 中定义对应方法: ```java public void onButtonClick(View view) { // 处理点击事件 } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值