Retrofit的使用,及介紹:
一,概念描述及理解:
Retrofit的底層是封裝的okhttp是對okhttp的封裝其內置okhttp框架,說retrfit是網絡請求的框架在這裏是不準確的,其實在這裏網絡請求還是使用的okhttp,Retrofit的作用在於網絡請求的高效,二者分工協作,宛如古人的『你耕地來我織布』
這裏我寫了大約7--8中小的案例,大家需要哪一種可以跳過不需要的部分,直接忽略:
我簡單的描述一下如何使用吧,它的使用其實很簡單,
1首先你要拿到一個根路徑,
2之後你要通過各種方式拼湊路徑
3拼湊是在@get註解中完成的,如果不需要參數,直接在註解中填入,抽象方法中就不需要參數了,
4如果需要各種參數,或者類型,get中的子路徑獲取需要經過各種拼湊,拼湊的數據需要用戶輸入,這時候,就將參數以形參的方式闖進抽象方法中,但是抽象方法中的形參也需要使用不同的註解,至於什麼是註解這裏我就不詳細說了,畢竟本章是講解Retrofit,代碼量太大了
簡單的說到這裏,下面進行詳細的代碼描述;
請牢記你需要的的案例的抽象方法名,不然我相信你會凌亂的;記住方法名到主方法中去尋找案例吧。
二,具體使用步驟:
1,添加依賴:
compile 'com.squareup.retrofit2:retrofit:2.0.2'
2,創建接口(名稱隨意,見名知義):
在接口中通過註解的方式,指定url,或者url中的一部分,在創建接口之前,先創建個url類用來盛放各種需要的url,這裏我準備了幾個url,可能只會用到其中一兩個而已,
先貼出來共享下:
public class Constant {
//荔枝新聞的完成的url地址
public final static String URL="http://litchiapi.jstv.com/" +
"api/GetFeeds?column=0&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41";
//荔枝新聞的跟路徑
public final static String BASE_URL="http://litchiapi.jstv.com/";
//茶葉品牌 http://42.120.4.67/api/app/business/category?app_id=161
public final static String TEABASE_URL="http://42.120.4.67/api/app/business/";
//下載圖片地址
public final static String IMAGE_URL="http://img5.imgtn.bdimg.com/it/u=4080105893,4096129906&fm=206&gp=0.jpg/";
//登錄地址 http://10.0.152.244:8080/WebServiceDemo/LoginServlet
public final static String LOGIN_URL="http://10.0.165.133:8080/WebServiceDemo/";
//上傳的網絡地址 http://192.168.1.103:8080/UploadServer/UpLoadAction
public final static String UPLOAD_URL="http://10.0.165.133:8080/UploadServer/";
}
下面我將開始創建我們的接口,在接口中我填寫了好幾個抽象方法,用來掩飾好幾種不同情況的url拼接案例,大家可以一種一種的看:
public interface INewsBiz {
/**
* 通過@GET註解標記位get請求 @GET中填寫baseUrl根路徑後的路徑
* 訪問的網絡地址由根路徑和@GET註解後的路徑連接組成
*/
//案例一:這種是將根路徑後面的路徑整個放入了get中進行拼接,相對比較簡單,後期和根url拼接
@GET("api/GetFeeds?column=0&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41")
//此處的返回值可以自行設置,這裏我就簡單的讓他返回請求體的內容:
Call<ResponseBody> getResonseBody();
@GET("api/GetFeeds?column=0&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41")
//案例二:此處的返回值我讓他返回的是String類型,具體返回邏輯我一會兒在主方法中創建:
Call<String> getJsonString();
//案例三:使用的是茶葉品牌的url,此處將根目錄以後的部分進行了截取,但是返回的是一個Tea對象的集合,至於tea對象的生成大家一定都會使用Gson吧,這個我就不細說了。
@GET("category?app_id=161")
Call<List<Tea>> getTeas();
//案例四:此處使用的是同案例一,但是path路徑不確定的情況情況下,使用{type}代替,當做抽象方法中的一個參數進行接收,
@GET("api/{type}?column=0&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41")
//這裏的path就是你要傳入的type類型,這裏@path“tyle”名稱一定要和@get();中的type同名,
Call<NewsInfo> getNewsInfo(@Path("type") String type);//String type="GetFeeds"
//案例五:有一個鍵值對的情況,如果不確定時,需要使用此方法,使用@query(鍵名)將你的值輸入:
@GET("category")//category?app_id=161
Call<List<Tea>> getTeaByNetWork(@Query("app_id") int id);
//案例六:如果鍵值對是很多的情況下,案例五很明先無法滿足需要,這時候需要使用@querymap接收一個map集合來進行拼湊。
@GET("api/GetFeeds")
Call<NewsInfo> getInfoByNetWork(@QueryMap Map<String, String> map);
//你也可以使用多種方式拼湊結合:使用{},加上參數的拼接等,都是可以靈活運行
案例七:
// @GET("api/{type}")
// Call<NewsInfo> getInfo(@Path("type") String type,@QueryMap Map<String,String> map);
//案例八:網絡下載圖片,
@GET("img")
Call<ResponseBody> downLoadImage();
//post形式提交表單數據 登錄 註冊,post需要服務器,這裏無法進行演示,但是代碼有,需要的話可以從自己的服務器中進行驗證,
//@post註解說明採用post提交的形式 @Field("向服務器提交的key")
@POST("LoginServlet")
@FormUrlEncoded
Call<String> login(@Field("username") String userName,
@Field("password") String password);
//上傳單個文件 @Field和@Part 客戶端向服務端攜帶參數發起請求
//@Part 可攜帶的參數類型更多樣 數據流等
@Multipart
@POST("UpLoadAction")
Call<ResponseBody> upLoadFile(@Part("img") RequestBody body);
//可以上傳表單中所有的數據 表單文本+附件
@POST("UpLoadAction")
Call<ResponseBody> upLoad(@Body() MultipartBody body);
}
下面是主方法中的代碼:
/**
* RetroFit 用來訪問網絡的第三方框架 http網絡請求工具
* RetroFit使用步驟:
* 1.定義一個接口(封裝url地址和數據請求)
* 2.實例化retrofit
* 3.調用retrofit實例創建接口服務對象
* 4.調用接口中的方法獲取Call對象
* 5.call對象請求(異步\同步請求)
*/
public class MainActivity extends AppCompatActivity {
private TextView tv;
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv= (TextView) findViewById(R.id.tv);
iv= (ImageView) findViewById(R.id.iv_show);
// initRetrofit01();
// initRetrofit02();
// initRetrofit03();
// initRetrofit04();
// initRetrofit05();
// initRetrofit06();
// initRetrofit07();
initRetrofit08();
}
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
String info= (String) msg.obj;
tv.setText(info);
}
};
/**
* 採用同步的訪問方式
*/
public void initRetrofit08(){
Retrofit retrofit=new Retrofit.Builder().baseUrl(Constant.BASE_URL).build();
final INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
new Thread(new Runnable() {
@Override
public void run() {
Call<ResponseBody> call=iNewsBiz.getResonseBody();
try {
//採用同步的形式請求數據
Response<ResponseBody> response=call.execute();
String str=response.body().string();
//將獲取的數據通過消息發送到主線程
Message message=Message.obtain();
message.obj=str;
handler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 下載網絡圖片
*/
public void initRetrofit07(){
Retrofit retrofit=new Retrofit.Builder().baseUrl(Constant.IMAGE_URL).build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
Call<ResponseBody> call=iNewsBiz.downLoadImage();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccess()){
// String str=response.body().string();
// byte[] buff=response.body().bytes();
InputStream in=response.body().byteStream();
Bitmap bm= BitmapFactory.decodeStream(in);
iv.setImageBitmap(bm);
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
/**
* get請求 請求通過@queryMap註解動態的傳遞多個參數
*/
public void initRetrofit06(){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
//column=0&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41"
Map<String,String> map=new HashMap<>();
map.put("column","0");
map.put("PageSize","10");
map.put("pageIndex","1");
map.put("val","100511D3BE5301280E0992C73A9DEC41");
Call<NewsInfo> call=iNewsBiz.getInfoByNetWork(map);
call.enqueue(new Callback<NewsInfo>() {
@Override
public void onResponse(Call<NewsInfo> call, Response<NewsInfo> response) {
if(response.isSuccess()){
List<NewsInfo.ParamzBean.FeedsBean> news=response.
body().getParamz().getFeeds();
StringBuffer sb=new StringBuffer();
for(NewsInfo.ParamzBean.FeedsBean feed:news){
sb.append(feed.getData().getSubject());
}
tv.setText(sb.toString());
}
}
@Override
public void onFailure(Call<NewsInfo> call, Throwable t) {
}
});
}
/**
* get請求 通過@query註解動態傳遞參數的值
*/
public void initRetrofit05(){
Retrofit retrofit=new Retrofit
.Builder()
.baseUrl(Constant.TEABASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
Call<List<Tea>> call=iNewsBiz.getTeaByNetWork(161);
call.enqueue(new Callback<List<Tea>>() {
@Override
public void onResponse(Call<List<Tea>> call, Response<List<Tea>> response) {
if(response.isSuccess()){
List<Tea> list=response.body();
StringBuilder sb=new StringBuilder();
for(Tea t:list){
sb.append(t.getProduct_cat_name());
}
tv.setText(sb.toString());
}
}
@Override
public void onFailure(Call<List<Tea>> call, Throwable t) {
}
});
}
/**
* get請求 通過佔位符指定path路徑
*/
public void initRetrofit04(){
Retrofit retrofit=new Retrofit
.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
Call<NewsInfo> call=iNewsBiz.getNewsInfo("GetFeeds");
call.enqueue(new Callback<NewsInfo>() {
@Override
public void onResponse(Call<NewsInfo> call, Response<NewsInfo> response) {
if(response.isSuccess()){
List<NewsInfo.ParamzBean.FeedsBean> news=response.
body().getParamz().getFeeds();
StringBuffer sb=new StringBuffer();
for(NewsInfo.ParamzBean.FeedsBean feed:news){
sb.append(feed.getData().getSubject());
}
tv.setText(sb.toString());
}
}
@Override
public void onFailure(Call<NewsInfo> call, Throwable t) {
}
});
}
/**
* 普通的get請求 返回的數據爲list集合
*/
public void initRetrofit03(){
Retrofit retrofit=new Retrofit
.Builder()
.baseUrl(Constant.TEABASE_URL)
//如果服務器返回的是json格式的數據 設置GsonConverterFactory後 實現對對象的轉化
//相當於對服務器返回的json字符串直接進行解析
.addConverterFactory(GsonConverterFactory.create())
.build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
Call<List<Tea>> call=iNewsBiz.getTeas();
call.enqueue(new Callback<List<Tea>>() {
@Override
public void onResponse(Call<List<Tea>> call, Response<List<Tea>> response) {
if(response.isSuccess()){
List<Tea> list=response.body();
StringBuilder sb=new StringBuilder();
for(Tea t:list){
sb.append(t.getProduct_cat_name());
}
tv.setText(sb.toString());
}
}
@Override
public void onFailure(Call<List<Tea>> call, Throwable t) {
}
});
}
/**
* 普通的get請求 返回的數據爲String類型
*/
public void initRetrofit02(){
Retrofit retrofit=new Retrofit
.Builder()
.baseUrl(Constant.BASE_URL)
//設置返回數據的適配器 get請求後可以返回String字符串類型的數據
.addConverterFactory(ScalarsConverterFactory.create())
.build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
Call<String> call=iNewsBiz.getJsonString();
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccess()){
tv.setText(response.body());
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
/**
* 普通get請求
*/
public void initRetrofit01(){
//創建retrofit的實例
Retrofit retrofit=new Retrofit
.Builder()
.baseUrl(Constant.BASE_URL)//必須存在 指定訪問網絡的根路徑
.build();
//根據接口的字節碼文件對象獲取接口對象
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
//調用接口中的方法
Call<ResponseBody> call=iNewsBiz.getResonseBody();
//調用call中的請求方法 enqueue()異步請求 execute()同步請求
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccess()){//成功的獲取響應
try {
String result=response.body().string();//獲取響應對象中的字符串
tv.setText(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
}
//Tea對象
public class Tea {
/**
* product_cat_id : 2032
* product_cat_name : 青茶
* product_cat_parent_id :
* industry_id : 161
*/
private String product_cat_id;
private String product_cat_name;
private String product_cat_parent_id;
private String industry_id;
public String getProduct_cat_id() {
return product_cat_id;
}
public void setProduct_cat_id(String product_cat_id) {
this.product_cat_id = product_cat_id;
}
public String getProduct_cat_name() {
return product_cat_name;
}
public void setProduct_cat_name(String product_cat_name) {
this.product_cat_name = product_cat_name;
}
public String getProduct_cat_parent_id() {
return product_cat_parent_id;
}
public void setProduct_cat_parent_id(String product_cat_parent_id) {
this.product_cat_parent_id = product_cat_parent_id;
}
public String getIndustry_id() {
return industry_id;
}
public void setIndustry_id(String industry_id) {
this.industry_id = industry_id;
}
}
//NeswsInfo對象
public class NewsInfo {
private String status;
private ParamzBean paramz;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public ParamzBean getParamz() {
return paramz;
}
public void setParamz(ParamzBean paramz) {
this.paramz = paramz;
}
public static class ParamzBean {
private int PageIndex;
private int PageSize;
private int TotalCount;
private int TotalPage;
private List<FeedsBean> feeds;
public int getPageIndex() {
return PageIndex;
}
public void setPageIndex(int PageIndex) {
this.PageIndex = PageIndex;
}
public int getPageSize() {
return PageSize;
}
public void setPageSize(int PageSize) {
this.PageSize = PageSize;
}
public int getTotalCount() {
return TotalCount;
}
public void setTotalCount(int TotalCount) {
this.TotalCount = TotalCount;
}
public int getTotalPage() {
return TotalPage;
}
public void setTotalPage(int TotalPage) {
this.TotalPage = TotalPage;
}
public List<FeedsBean> getFeeds() {
return feeds;
}
public void setFeeds(List<FeedsBean> feeds) {
this.feeds = feeds;
}
public static class FeedsBean {
private int id;
private int oid;
private String category;
private DataBean data;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOid() {
return oid;
}
public void setOid(int oid) {
this.oid = oid;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public static class DataBean {
private String subject;
private String summary;
private String cover;
private String pic;
private String format;
private String changed;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getChanged() {
return changed;
}
public void setChanged(String changed) {
this.changed = changed;
}
}
}
}
}
//LogInActivity
public class LoginActivity extends AppCompatActivity{
private EditText et_name,et_pwd;
private TextView tv;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
et_name= (EditText) findViewById(R.id.et_name);
et_pwd= (EditText) findViewById(R.id.et_pwd);
tv= (TextView) findViewById(R.id.tv_result);
}
public void Login(View view){
Retrofit retrofit=new Retrofit.Builder().
baseUrl(Constant.LOGIN_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
String name=et_name.getText().toString().trim();
String pwd=et_pwd.getText().toString().trim();
Call<String> call=iNewsBiz.login(name,pwd);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccess()){
tv.setText(response.body());
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
}
//UpLoadActivity
public class UpLoadActivity extends AppCompatActivity{
private EditText et_name;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload);
et_name= (EditText) findViewById(R.id.et_username);
}
/**
* 點擊按鈕上傳附件(文件 圖片 音視頻 文本...)
*/
public void uploadFile(View view){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Constant.UPLOAD_URL).build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
//需要上傳的文件名稱
String fileName= Environment.getExternalStorageDirectory()
.getAbsolutePath()+File.separator+"dog.jpg";
File file=new File(fileName);
// RequestBody 請求體對象 抽象類 MultipartBody子類
RequestBody requestBody=new MultipartBody
.Builder()
.addFormDataPart("app","dog.jpg",
MultipartBody.create(MediaType.parse("multipart/form-data"),file))
.build();
Call<ResponseBody> call=iNewsBiz.upLoadFile(requestBody);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccess()){
try {
Log.i("tag",response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
/**
* 上傳表單和附件數據
* @param view
*/
public void uploadForm(View view){
String userName=et_name.getText().toString().trim();
File file=new File(Environment.
getExternalStorageDirectory().
getAbsolutePath()+File.separator+"dog.jpg");
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Constant.UPLOAD_URL).build();
INewsBiz iNewsBiz=retrofit.create(INewsBiz.class);
//將需要上傳的表單和文件數據添加到MultipartBody對象中 請求體對象
MultipartBody body=new MultipartBody.Builder()
.addFormDataPart("name",userName)//需要上傳的表單數據
.addFormDataPart("app","dog.jpg",
MultipartBody.create(MediaType.parse("multipart/form-data"),file))//需要上傳的文件數據
.build();
Call<ResponseBody> call=iNewsBiz.upLoad(body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccess()){
try {
Log.i("tag",response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
}
//longin佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入用戶名"
android:textSize="30sp"/>
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入密碼"
android:inputType="textPassword"
android:textSize="30sp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登錄"
android:textSize="25sp"
android:onClick="Login"/>
<TextView
android:id="@+id/tv_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:textColor="#aa0000"
android:text="result"/>
</LinearLayout>
//主活動佈局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.yztc.retrofitdemo.MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<ImageView
android:id="@+id/iv_show"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
//上傳文件upload佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:hint="請輸入用戶名"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上傳文件"
android:textSize="25sp"
android:onClick="uploadFile"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上傳全部"
android:textSize="25sp"
android:onClick="uploadForm"/>
</LinearLayout>
希望我的只寫源代碼能夠幫助到需要的。