通常情况下会将网络操作提取到一个公共类里,并提供静态方法
网络请求通常属于耗时操作,需要另开线程,但如果直接在上文中的静态方法内部开启一个线程,会导致服务器响应的数据无法返回,所有耗时逻辑都是在子线程中进行的,静态方法会在服务器还没来得及响应的时候就执行结束,当然也就无法返回响应数据了。
解决方法是使用java回调机制
- HttpURLConnection情况
首先定义一个接口
public interface HttpCallbackListener {
void onFinish(String response);
void onError(Exception e);
}
在接口中定义了两个方法,onFinish()服务器成功响应请求时调用,onError()进行网络操作出现错误时调用
在发送请求的方法中传入这个接口参数,并在内部开启一个子线程,在子线程中执行具体的网络操作。
注意子线程是无法通过return语句返回数据的,因此将服务器响应的参数传入或者异常传入接口的方法中
public class HttpUtil {
public static void sendHttpRequest(final String address,final HttpCallbackListener listener){
//注意子线程中使用的变量要被声明成final
//会提示accedded from within inner class,needs to be declared final
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection=null;
try{
URL url=new URL(address);
connection=(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDoOutput(true);//这两句是啥
InputStream in=connection.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder response=new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
if(listener!=null){
//回调onFinish()方法
listener.onFinish(response.toString());
}
}catch (Exception e){
if(listener!=null){
//回调onError()方法
listener.onError(e);
}
}finally {
if(connection!=null){
connection.disconnect();
}
}
}
}).start();
}
}
调用网络请求方法
HttpUtil.sendHttpRequest(address,new HttpCallbackListener(){
@Override
public void onFinish(String response){
//在这里根据返回内容执行具体的逻辑
}
@Override
public void onError(Exception e){
//对异常情况进行处理
}
});
- OkHttp
OkHttp就比刚才方便多了
OkHttp库自带回调接口okhttp3.Callback注意newCall之后不调用execute()方法改用enqueue()方法并把okhttp3.Callback参数传入
OkHttp在enqueue()方法内部开子线程,然后在子线程中执行Http请求,并将最终请求结果回调到okhttp3.Callback中
public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder()
.url(address)
.build();
client.newCall(request).enqueue(callback);
}
使用
HttpUtil.sendOkHttpRequest(address,new okhttp3.Callback(){
@Override
public void onResponse(Call call,Response reponse) throws IOException{
String responseData=response.body().string();
}
@Override
public void onFailure(Call call,IOException e){
//
}
});