“我有一个需求是,,,”
“用回调函数实现,,,”
卧槽,什么是回调函数?卧槽,我也不知道要怎么说,回调函数的定义解释起来,只会让初学者越来越懵,所以我们就从“应用场景”入手结合代码理解。
很多时候你从模仿开始,自己动手实现一下,一切就不言而喻了
1.应用场景
其实,在我们平时的开发中,也经常遇到回调函数
1.1 控件的监听事件
mLongin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
//这里操作逻辑
}
});
1.2 使用第三方SDK也会大量接触回调函数
例如在使用第三方登录的SDK的时候,触发登录事件一般会监听回调函数
mLongin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
new HttpUtils().send("loginUrl", new ResponseCallback() {
@Override
public void onSuccess(JSONObject responseInfo) {
// TODO Auto-generated method stub
}
@Override
public void onFailure(int errorCode, String msg) {
// TODO Auto-generated method stub
}
});
}
});
代码中onSuccess,onFailure就是回调函数
2.代码实现
由于最近公司需要做SDK的相关项目,了解一下回调函数,现在就模拟开发SDK的身份写一个登录时的回调函数给开发者调用,简单分析代码结构如下,分为三部分
- 回调接口
- 接口实现类
- activity调用
2.1.回调接口
开发者调用登录接口最简单的会有两种返回情况:
- 成功:onSuccess
- 失败:onFailure
package com.ruffian.android.callback;
import org.json.JSONObject;
/**
* 请求服务器结果回调接口
*
* @author Ruffian
* @date 2015年12月8日
*
*/
public interface ResponseCallback {
/**
* 执行成功回调接口
*
* @param responseInfo
* @author Ruffian
* @date 2015年12月8日
*/
public void onSuccess(JSONObject responseInfo);
/**
* 执行失败回调接口
*
* @param errorCode
* @param msg
* @author Ruffian
* @date 2015年12月8日
*/
public void onFailure(int errorCode, String msg);
}
2.2.接口实现类
构建一个接口实现类,其实这里说是接口的实现类是不太正确的,为了方便理解,暂且这样称呼,打个不太恰当的比方:为接口函数赋值,不知道可以不可以这样说,但是可以这样来理解。我们在接口实现类里面处理逻辑,做一些操作,然后将特定的返回值设置到对应的接口方法中,等待调用者调用。
构建一个发送请求的方法send 这个方法只有接口的引用,在处理完登录的逻辑之后为对应的方法这是返回值。代码如下
package com.ruffian.android.utils;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
import android.util.Log;
import com.ruffian.android.callback.ResponseCallback;
/**
* 访问网络的工具类
*
* @author Ruffian
* @date 2015年12月8日
*
*/
public class HttpUtils {
/**
* 发送网络请求 ;模拟GET方式提交,不带参数
*
* @param tagetUrl后台接口地址
* @param callback回调接口
* @author Ruffian
* @date 2015年12月8日
*/
public void send(final String tagetUrl, final ResponseCallback callback) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL(tagetUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000); // 设置连接超时为5秒
connection.setRequestMethod("GET"); // 设定请求方式
connection.connect(); // 建立到远程对象的实际连接
// 判断是否正常响应数据
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// 这里模拟服务器返回结果
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", "value");
// 将结果设置到回调函数
callback.onSuccess(jsonObject);
} else {
// 请求后台出错
callback.onFailure(connection.getResponseCode(), "访问出错");
}
} catch (Exception e) {
// 这里模拟请求后台出错
callback.onFailure(999, "未知错误");
e.printStackTrace();
} finally {
// 这里模拟请求后台出错
callback.onFailure(999, "未知错误");
if (connection != null) {
connection.disconnect(); // 中断连接
}
}
}
}).start();
}
}
正如代码中所示,新建线访问网络,等待后台返回结果,如果请求成功则将返回值设置到onSuccess 方法中
<span style="white-space:pre"> </span>// 这里模拟服务器返回结果
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", "value");
// 将结果设置到回调函数
callback.onSuccess(jsonObject);
如果请求失败则将对应的返回值设置到onFailure方法中
<span style="white-space:pre"> </span>// 请求后台出错
callback.onFailure(connection.getResponseCode(), "访问出错");
<span style="white-space:pre"> </span>// 这里模拟请求后台出错
callback.onFailure(999, "未知错误");
2.3.activity调用
在activity中调用登录接口,展示返回值,模拟成功的网址使用百度:https://www.baidu.com/ 失败网址:http://123.59.71.217:8080/tvgamer/index.do
在登录按钮点击的时候联网登录,当联网处理操作完成之后会执行回调函数的逻辑(在这里就是战士返回结果)
package com.ruffian.android;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.ruffian.android.callback.ResponseCallback;
import com.ruffian.android.utils.HttpUtils;
@SuppressLint("HandlerLeak")
public class MainActivity extends Activity {
/**
* 模拟登录接口地址
* 百度https://www.baidu.com/
* 错误地址http://123.59.71.217:8080/tvgamer/index.do
*/
private static final String LOGIN_URL = "https://www.baidu.com/";
// 更新结果(UI)
private static final int UPDATE_RESULT = 1001;
private Button mLongin;// 登录按钮
private TextView mResult;// 登录结果
private String mResultText;// 返回结果
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLongin = (Button) findViewById(R.id.login);
mResult = (TextView) findViewById(R.id.result);
mLongin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
new HttpUtils().send(LOGIN_URL, new ResponseCallback() {
@Override
public void onSuccess(JSONObject responseInfo) {
// TODO Auto-generated method stub
// 这里操作成功的逻辑
mResultText = "访问接口成功,结果:" + responseInfo;
uiHandler.sendMessage(uiHandler.obtainMessage(
UPDATE_RESULT, mResultText));
}
@Override
public void onFailure(int errorCode, String msg) {
// TODO Auto-generated method stub
// 这里操作失败的逻辑
mResultText = "访问接口出错,错误代码:" + errorCode + ",错误详情:"
+ msg;
uiHandler.sendMessage(uiHandler.obtainMessage(
UPDATE_RESULT, mResultText));
}
});
}
});
}
Handler uiHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_RESULT:
String result = (String) msg.obj;
mResult.setText(result);
break;
}
};
};
}
运行结果图