Listener监听器运用的就是观察者模式编写,在Android setOnClickListener按钮点击事件中,我们点击Button按钮之后,会进入到内部的“onClick”回调方法中,然后做一些事情,那么为什么会进入“onClick”回调方法中呢?下面小编会自定义Listener监听器事件,让大家了解Android OnClickListener点击事件的原理。
先看一下我们的Android Button按钮点击事件这一部分的代码:
Button btnExample = (Button) findViewById(R.id.btnExample); btnExample.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Do something here } });
下面我们开始来自定义Listener监听器,让各位了解OnClickListener事件为什么会有这样惊奇的效果,下面是实现步骤。
1.定义一个Listener接口类
首先定义一个Listener接口类,定义这个接口类就是为了模仿“View”这个类里面的“OnClickListener”接口,里面自定义两个接口方法,代码如下:
public class MyCustomObject { // 步骤一: MyCustomObject在类内部定义这个接口类 public interface MyCustomObjectListener { // 初始化 public void onObjectReady(String title); // 加载数据 public void onDataLoaded(SomeData data); } }
2.创建Listener监听器的Setter方法,采用Setter回调
首先在MyCustomObject这个类的内部,MyCustomObjectListener接口的外部,添加“MyCustomObjectListener”的成员变量,代码如下:
public class MyCustomObject { // 步骤一:... // 步骤二:添加成员变量 private MyCustomObjectListener listener; }
添加一个setter方法,模仿Button按钮的“setOnClickListener”方法,代码如下:
public class MyCustomObject { // 步骤一:... // 步骤二:... // 步骤三:添加匿名构造函数与setter方法 public MyCustomObject() { // 将listener置空是因为我们不采用构造器回调 this.listener = null; } // Setter方法回调,步骤三 public void setCustomObjectListener(MyCustomObjectListener listener) { this.listener = listener; } }
3.实现Listener监听器回调事件,模拟Button按钮点击事件
在此处,我们开始实现最上方的类似的Button setOnClickListener点击事件,代码如下所示:
public class MyParentActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // ... // 模式button按钮类 MyCustomObject object = new MyCustomObject(); // 步骤四:在Activity中使用类似的点击事件 object.setCustomObjectListener(new MyCustomObject.MyCustomObjectListener() { @Override public void onObjectReady(String title) { // Code to handle object ready } @Override public void onDataLoaded(SomeData data) { // 从网络中加载的数据在此处使用,SomeData表示回调的数据 // 思考,为什么SomeData此时会有数据过来? } }); } }
4.完整代码,思考?
我们需要思考,为什么在Activity中使用了setCustomObjectListener这个Setter方法之后,就会将上方的“SomeData”值回调过来了呢?这是因为我们在new MyCustomObject()这个类的时候,我们在构造函数中实现了自定义的“loadDataAsync()”方法,我们都知道,构造函数是随着类的加载而加载的,所以在初始化的时候,就可以给“SomeData”赋值了,代码如下:
public class MyCustomObject { // Listener defined earlier public interface MyCustomObjectListener { public void onObjectReady(String title); public void onDataLoaded(SomeData data); } // Member variable was defined earlier private MyCustomObjectListener listener; // new对象时会调用此构造函数 public MyCustomObject() { // set null or default listener or accept as argument to constructor this.listener = null; loadDataAsync(); } // Setter方法回调 public void setCustomObjectListener(MyCustomObjectListener listener) { this.listener = listener; } public void loadDataAsync() { AsyncHttpClient client = new AsyncHttpClient(); client.get("https://mycustomapi.com/data/get.json", new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { // 解析网络中加载过来的数据 SomeData data = SomeData.processData(response.get("data")); // Do some other stuff as needed.... // Now let's trigger the event if (listener != null) listener.onDataLoaded(data); // <---- 调用方法并传值(SomeData) } }); } }
从上方的代码我们就可以看出“SomeData”为什么在实现setCustomObjectListener()回调函数时就有值了,这就是很多回调函数的原理了。