Android开发,addlistener和setlistener的区别

做Android开发稍微久一点的都知道,android之前的监听器基本都是setlistener,比如setOnClickListener,setTextChangeListener。

但是后来,android中很多的setlistener都被废弃了,用addlistener来替代,比如上面的setTextChangeListener。

本文主要就是用于探讨setlistener和addlistener的区别。

我们就以setOnClickListener和addTextChangedListener举例

1、查看源码

/**
     * Register a callback to be invoked when this view is clicked. If this view is not
     * clickable, it becomes clickable.
     *
     * @param l The callback that will run
     *
     * @see #setClickable(boolean)
     */
    public void setOnClickListener(@Nullable OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }
/**
     * Adds a TextWatcher to the list of those whose methods are called
     * whenever this TextView's text changes.
     * 

* In 1.0, the {@link TextWatcher#afterTextChanged} method was erroneously * not called after {@link #setText} calls. Now, doing {@link #setText} * if there are any text changed listeners forces the buffer type to * Editable if it would not otherwise be and does call this method. */ public void addTextChangedListener(TextWatcher watcher) { if (mListeners == null) { mListeners = new ArrayList(); } mListeners.add(watcher); }

可以看到,setListener直接是给View中的一个listener赋了值。
而addListener是将该listener添加到了一个arraylsit集合里面。
从这里我们可以猜测,setListener只能设置一个,addListenr可以设置多个。
下面我们来看看具体。

2、测试setListener

我在xml中设置了一个按钮

代码中:

class ListenerTestActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_listener_test)
        btn_test_setListener.setOnClickListener {
            Log.e("set1", "1-listener is clicked")
        }
        btn_test_setListener.setOnClickListener {
            Log.e("set2", "2-listener is clicked")
        }
    }
}
恩, 测试demo我使用的语言是kotlin,这里大家应该看得懂,也不复杂,也不影响结果,就不再写一个java版本了。
可以看到,我连续设置了两个点击事件给按钮。

11-08 11:10:56.508 16788-16788/com.stanny.xbtest E/set2: 2-listener is clicked
11-08 11:10:57.475 16788-16788/com.stanny.xbtest E/set2: 2-listener is clicked
11-08 11:10:57.866 16788-16788/com.stanny.xbtest E/set2: 2-listener is clicked
可以看到,只有第二个点击事件被调用了,而第一个完全被覆盖了。


3、测试addListener

et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    Log.e("add1", "1-listener is changed")
                }
            }

        })
        et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    Log.e("add2", "2-listener is changed")
                }
            }

        })
这里我给我的输入框添加了两个监听,都是在判断输入文字长度为2时,打印一段log

11-08 11:14:49.050 21397-21397/com.stanny.xbtest E/add1: 1-listener is changed
11-08 11:14:49.050 21397-21397/com.stanny.xbtest E/add2: 2-listener is changed

可以看到,两个监听,都被打印了。


4、进一步测试addListener

et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    finish()//修改位置
                }
            }

        })
        et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                   Log.e("add2", "2-listener is changed")
                }
            }

        })
我们第一个监听直接finish掉当前activity,那么第二个还会执行么
11-08 11:30:48.601 6465-6636/com.stanny.xbtest E/add2: 2-listener is changed
可以看到,即使activity已经被finish掉了,第二个监听仍然会执行

那么,你可能会说了,因为这两个是同时发生的,所以才会出现仍然会执行。好,我们继续


5、再进一步测试

et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    finish()
                }
            }

        })
        et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    var timer = Timer()//修改位置
                    timer.schedule(object : TimerTask() {
                        override fun run() {
                            Log.e("add2", "2-listener is changed")
                        }

                    }, 1000)
                }
            }
        })

我们给第二个监听的打印,一个等待时间,而这时候,该activity已经被finish了

11-08 11:36:02.633 11617-11855/com.stanny.xbtest E/add2: 2-listener is changed

也是会执行的,我们的手机上,明明此时activity已经返回了上一级,但是log仍然打印出来了。

那还有没有什么问题?

有的,因为我们现在只是简单的打印了文字,和当前的activity的数据或者控件都没有联系,所以,会不会是这个原因呢?


6、最后一步测试

et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    finish()
                }
            }

        })
        et_test_addListener.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (et_test_addListener.text.length == 2) {
                    var timer = Timer()
                    timer.schedule(object : TimerTask() {
                        override fun run() {
                            Log.e("add2", "2-listener is changed")
                            btn_test_setListener.setText("123")//修改位置
                        }

                    }, 1000)
                }
            }
        })
可以看到,我在第二个延时操作的时候,不仅仅打印了log,还给一个按钮设置了文字。

之前我们怀疑因为没涉及到控件,所以不会报错,这次,我们测试在activity被finish掉之后,对控件进行操作。

因为已经finish了,我们也看不到按钮是否改变了文字,但是,我可以确定,没有产生崩溃,没有报错信息。


那么,我们想知道,这个activity真的已经被finish掉了么?还是说,要等到添加的监听都实现完了才会被finish。

这个问题,等有时间,我再来研究。


你可能感兴趣的:(Android基础开发,源码分析)