工作内容:
1.OkHttp的Post,Get请求
2.Retrofit的使用【更多详情可以参考】
学习分享:[代码中使用了ButterKnife,参考ButterKnife使用]
1.OkHttp的使用步骤【注意同步加载最好放入子线程中:同步加载call.execute,异步加载call.enqueue】
使用OkHttp注意:
1.同步加载最好放入子线程中(网络请求很可能耗时过长导致出错)
2.一个onResponse方法中response.body().string()只能使用一次(可以定义1个String变量接受它的值,重复使用)
① 添加依赖
compile 'com.squareup.okhttp3:okhttp:3.4.1'
② 使用步骤如下:
1.定义规范接口
import okhttp3.Call;
/**
* Created by Administrator on 2016/9/27.
* 接口:用于规范OkHttp请求的方法
*/
public interface MyOkHttpCall {
//获取历史上的今天的信息
Call getHistoryTodayInfoOnPost(String string);
//获取天气接口
Call getWeatherOnGet();
}
2.定义OkHttp工具类
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrodemo.liu.com.retrofitdemo.interface_.MyOkHttpCall;
/**
* Created by Administrator on 2016/9/27.
* 使用单列模式写OkHttp的网络请求工具类
* 实现接口
*/
public class RequestOnOKHttpUtil implements MyOkHttpCall {
private final String urlHostory = "http://api.avatardata.cn/GuoNeiNews/Query";//接口(不含参数)
private final String urlWeather = "http://api.avatardata.cn/Weather/Query?" +
"key=615dcc76298a44329b8db1896852b0cb&cityname=成都";//天气接口(含参数)
private OkHttpClient okHttpClient;
private static RequestOnOKHttpUtil requestOnOKHttp = null;
public static RequestOnOKHttpUtil getInstance(){
if(requestOnOKHttp == null){
requestOnOKHttp = new RequestOnOKHttpUtil();
}
return requestOnOKHttp;
}
private RequestOnOKHttpUtil(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
//添加拦截器(用于打印请求字段[包括请求头,请求体等信息])
okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
}
/**
* OkHttp--Post方式请求数据
* Post请求时需要特别注意请求参数
* @param Parms
* @return
*/
@Override
public Call getHistoryTodayInfoOnPost(String Parms) {
String requestParms = "key=1dc41caa4c454d48a00e5f970c9fdfcb&page=1&rows=10";
RequestBody requestBody = RequestBody.create(null,requestParms);
Request request = new Request.Builder()
.url(urlHostory)
.post(requestBody) //post方式请求数据,requestBody是请求体
.build();
Call call = okHttpClient.newCall(request);
return call;
}
/**
* OkHttp--Get方式获取天气数据
* Get请求时url中填入完整的请求地址+请求参数
*/
@Override
public Call getWeatherOnGet() {
Request request = new Request.Builder()
.url(urlWeather)
.get() //get方式请求数据
.build();
Call call = okHttpClient.newCall(request);
return call;
}
}
OkHttp_Post请求方式的RequestBody获取方式(老版本)
RequestBody formBody = new FormEncodingBuilder()//老版本获取ResquestBody的方式
.add("name", "Cuber")
.add("age", "26")
.build();
Request request = new Request.Builder()
.url(url)
.post(RequestBody)
.build();</span>
OkHttp_Post请求方式的RequestBody获取方式(新版本)
//新版本的请求体获取方式
FormBody body= new FormBody.Builder()
.add("menu","土豆")
.add("key","08b127d3d67bc05a617fe7aebf1d9670")
.build();
request = new Request.Builder()
.post(body)
.url(baseUrl)
.build();
return client.newCall(request);
3.Callback后台转前台执行
import android.os.Handler;
import android.os.Looper;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
/**
* Created by Administrator on 2016/9/27.
* Callback的onFailure,onPosnse方法都是在后台线程执行
* 这里使用Handler将后台执行转成Ui主线程执行
*/
public abstract class MyOkHttpCallback implements Callback {
//Looper.getMainLooper()表示放到主UI线程去处理,不添加表示在当前线程处理
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void onFailure(final Call call, final IOException e) {
handler.post(new Runnable() {
@Override
public void run() {
uiThreadDoOnFailure(call,e);
}
});
}
@Override
public void onResponse(final Call call,final Response response) throws IOException {
handler.post(new Runnable() {
@Override
public void run() {
uiThreadDoOnResponse(call,response);
}
});
}
public abstract void uiThreadDoOnFailure(Call call, IOException e);
public abstract void uiThreadDoOnResponse(Call call, Response response);
}
3.调用工具类的方法(activity代码)
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
import butterknife.ButterKnife;
import okhttp3.Call;
import okhttp3.Response;
import retrodemo.liu.com.retrofitdemo.interface_.MyOkHttpCallback;
import retrodemo.liu.com.retrofitdemo.requestutil.RequestOnOKHttpUtil;
public class OkHttpActivity extends AppCompatActivity {
private int pages = 1;
private Gson gson = new Gson();
private List<NewsInfo.ShowapiResBodyBean.PagebeanBean.ContentlistBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ok_http);
ButterKnife.bind(this);
requestOnPost();
requestOnGet();
}
//天气数据Okhttp_get
private void requestOnGet() {
Call call = RequestOnOKHttpUtil.getInstance().getWeatherOnGet();
/**
* 异步加载
* 请求加入调度
* 同步加载方法:call.execute();会抛出IO异常
*/
call.enqueue(new MyOkHttpCallback() {
@Override
public void uiThreadDoOnFailure(Call call, IOException e) {
Log.e("___测试___Get_OnFailure", "Get_OnFailure");
}
@Override
public void uiThreadDoOnResponse(Call call, Response response) {
try {
Log.e("___测试___Get_onResponce", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
//历史上的今天OkHttp-post
private void requestOnPost() {
String parms = "yue=8&ri=28&type=1&page=1&rows=10";
Call call = RequestOnOKHttpUtil.getInstance().getHistoryTodayInfoOnPost(parms);
/**
* 异步加载
* 请求加入调度
*/
call.enqueue(new MyOkHttpCallback() {
@Override
public void uiThreadDoOnFailure(Call call, IOException e) {
Toast.makeText(OkHttpActivity.this, "uiThreadDoOnFailure_Post", Toast.LENGTH_SHORT).show();
}
@Override
public void uiThreadDoOnResponse(Call call, Response response) {
try {
Log.e("___测试___Post", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
③ 结果演示
2.Retrofit的常规使用【附带上注解的使用简介】
① 导包:/添加依赖【编程工具Android studio】
compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'
② 创建请求接口【配置请求参数】
import android.support.annotation.Nullable; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Path; import retrofit2.http.Query; /** * Created by Administrator on 2016/9/28. */ public interface RetrofitCall { //retrofit-getFruit @GET("/cook/query?key=08b127d3d67bc05a617fe7aebf1d9670" + "&menu=土豆&rn=10&pn=3") Call<ResponseBody> getFruit(); //retrofit-postFruit @POST("/cook/query.php") // @Headers("content-type:json") //添加头信息固态,放入参数中则变成动态添加 Call<ResponseBody> postFruit(@Query("key") String key , @Query("menu") String menu , @Nullable @Query("rn") String rn , @Nullable @Query("pn") String pn); //okhttp-get okhttp3.Call getFruitOkHttp(); //okhttp-post okhttp3.Call postFruitOkHttp(); } /** * 注解说明(Retrofit请求) * @GET @POST是请求方式 * @Header 添加头信息 * * 参数部分使用下列注解 * @Path 表示替换【必填】 * 例: * @GET("book/{id}") * Call<BookResponse> getBook(@Path("id") String id); * @Query 表示可选部分【非必填】代码中有用到,这里就不举例了 * @QueryMap map<String str> options 表示map形式传递可选参数 * 例: * @GET("book/search") * Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options); * @field表单方式提交 * 例 * @FormUrlEncoded * @POST("book/reviews") * Call<String> addReviews(@Field("book") String bookId, @Field("title") String title, * @Field("content") String content, @Field("rating") String rating); * @FieldMap 与上面类似只是变成了map *例: * @FormUrlEncoded * @POST("book/reviews") * Call<String> addReviews(@FieldMap Map<String, String> fields); * @Body 请求参数有多个,那么统一封装到类中应该会更好, * 例; * @FormUrlEncoded * @POST("book/reviews") * Call<String> addReviews(@Body Reviews reviews); * public class Reviews { * public String book; * public String title; * public String content; * public String rating; * } * 还有一个多部分(比较少用) */
③ 创建业务类【处理网络请求】
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import online.liu.com.onlinedemo.inter.RetrofitCall;
import online.liu.com.onlinedemo.obj.User;
import online.liu.com.onlinedemo.obj.UserResult;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Body;
import retrofit2.http.Query;
/**
* Created by Administrator on 2016/9/28.
*/
public class RequestUtil implements RetrofitCall{
private static RequestUtil requestUtil = null;
private OkHttpClient client = null;
private RetrofitCall retrofitCall;
private String Base_postUrl = "http://admin.syfeicuiedu.com";
private String Base_fruitUrl = "http://apis.juhe.cn";
private String Base_fruitUrl_okhttpGet = "http://apis.juhe.cn/cook/query?" +
"key=08b127d3d67bc05a617fe7aebf1d9670" +
"&menu=土豆&rn=10&pn=3";
private String Base_fruitUrl_okhttpPost = "http://apis.juhe.cn/cook/query";
//单例模式
public static RequestUtil getInstance(){
if(requestUtil == null){
requestUtil = new RequestUtil();
}
return requestUtil;
}
//构造函数
private RequestUtil(){
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client = new OkHttpClient.Builder()
.addInterceptor(interceptor) //添加拦截器【Log.d方式打印请求信息】
.build();
}
//retrofit-Get
@Override
public Call<ResponseBody> getFruitData() {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(Base_fruitUrl)
//添加Gson转换器,将返回Json字符串转换成实体类
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofitCall = retrofit.create(RetrofitCall.class);
return retrofitCall.getFruitData();
}
//retrofit-Post-login
@Override
public Call<UserResult> postData(@Body User user) {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(Base_postUrl)
.build();
retrofitCall = retrofit.create(RetrofitCall.class);
return retrofitCall.postData(user);
}
//retrofit-Post-fruit
@Override
public Call<ResponseBody> postFruit(@Query("key") String key, @Query("menu") String menu, @Query("rn") int rn, @Query("pn") int pn) {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(Base_fruitUrl)
.build();
retrofitCall = retrofit.create(RetrofitCall.class);
return retrofitCall.postFruit(key,menu,rn,pn);
}
//okhttp-get-fruit
@Override
public okhttp3.Call getFruitOkHttp() {
Request request = new Request.Builder()
.url(Base_fruitUrl_okhttpGet)
.get()
.build();
return client.newCall(request);
}
//okhttp-post-fruit
@Override
public okhttp3.Call postFruitOkHttp() {
RequestBody requestBody = RequestBody.create(null,"key=08b127d3d67bc05a617fe7aebf1d9670&menu=土豆&rn=10&pn=3");
Request request = new Request.Builder()
.url(Base_fruitUrl_okhttpPost)
.post(requestBody)
.build();
return client.newCall(request);
}
}
④ Presender类【这里没有写这处理类,直接写在了Activity中】
mport android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.OnClick;
import okhttp3.ResponseBody;
import online.liu.com.onlinedemo.R;
import online.liu.com.onlinedemo.conn.RequestUtil;
import online.liu.com.onlinedemo.obj.Friut;
import online.liu.com.onlinedemo.obj.User;
import online.liu.com.onlinedemo.obj.UserResult;
import online.liu.com.onlinedemo.tools.LogTool;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Activity类
* 任务:
* 点击按钮,通过下列的方式去请求网络数据()
* 1.OKHttp_get
* 2.OKHttp_post
* 3.Retrofit_get
* 4.Retrofit_post
*/
public class FruitActivity extends AppCompatActivity {
private Gson gson = new Gson();
private RequestUtil requestUtil;
private List<Friut.ResultBean.DataBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fruit);
ButterKnife.bind(this);
requestUtil = RequestUtil.getInstance();
}
private void postFruitOnRetrofit() {
requestUtil.postFruit("08b127d3d67bc05a617fe7aebf1d9670", "土豆", 10, 3).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(FruitActivity.this, "PostFruitOnRetrofit_onResponse应成功", Toast.LENGTH_SHORT).show();
LogTool.e("PostFruitOnRetrofit_onResponse响应成功");
try {
LogTool.e("postFruit_OnRetrofit_onResponse:" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
LogTool.e("postFruit_OnRetrofit_onFailure");
Toast.makeText(FruitActivity.this, "postFruit_OnRetrofit_onFailure", Toast.LENGTH_SHORT).show();
}
});
}
private void getFruitOnRetrofit() {
requestUtil.getFruitData().enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(FruitActivity.this, "getDataOnRetrofit_onResponse", Toast.LENGTH_SHORT).show();
LogTool.e("getDataOnRetrofit_onResponse响应成功");
try {
LogTool.e("getDataOnRetrofit_onResponse:" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
LogTool.e("getDataOnRetrofit_onFailure");
Toast.makeText(FruitActivity.this, "getDataOnRetrofit_onFailure", Toast.LENGTH_SHORT).show();
}
});
}
//常用于账号/密码验证
private void postDataOnRetrofit() {
requestUtil.postData(new User("zhang", "123")).enqueue(new Callback<UserResult>() {
@Override
public void onResponse(Call<UserResult> call, Response<UserResult> response) {
LogTool.e("响应成功");
UserResult userResult = response.body();
LogTool.e("postDataOnRetrofit_onResponse:" + userResult.getErrmsg());
Toast.makeText(FruitActivity.this, "postDataOnRetrofit_onResponse", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<UserResult> call, Throwable t) {
LogTool.e("postDataOnRetrofit_onFailure");
Toast.makeText(FruitActivity.this, "postDataOnRetrofit_onFailure", Toast.LENGTH_SHORT).show();
}
});
}
private void getFruitOnOkHttp() {
requestUtil.getFruitOkHttp().enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
LogTool.e("getFruitOnOkHttp_onFailure");
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
LogTool.e("getFruitOnOkHttp_onResponse" + response.body().string());
}
});
}
private void postFruitOnOkHttp() {
requestUtil.postFruitOkHttp().enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
LogTool.e("postFruitOnOkHttp_onFailure");
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
LogTool.e("postFruitOnOkHttp_onResponse" + response.body().string());
}
});
}
@OnClick({R.id.Okhttp_get, R.id.Okhttp_post, R.id.retrofit_get, R.id.retrofit_post})
public void onClick(View view) {
switch (view.getId()) {
case R.id.Okhttp_get:
getFruitOnOkHttp();
break;
case R.id.Okhttp_post:
postFruitOnOkHttp();
break;
case R.id.retrofit_get:
getFruitOnRetrofit();
break;
case R.id.retrofit_post:
postFruitOnRetrofit();
// postDataOnRetrofit();
break;
}
}
}
⑤ 执行效果