廢話:
強行開啟了Retrofit的學(xué)習(xí)模式坡疼,但是發(fā)現(xiàn)啊彬呻,我找到的一些入門文章,簡直不要太坑柄瑰,敲不出來demo不要緊啊闸氮,你得講的讓我看懂吧?好教沾,有一篇能看懂的了蒲跨,喂能不能講完啊,講一半死球了不做完一套demo幾個意思授翻!
OK既然沒有好的Retrofit第一炮的文章或悲,那么我的機會就來了
看完本文并且do it你將收獲
- 使用Retrofit進行一次基礎(chǔ)的不能再基礎(chǔ)的網(wǎng)絡(luò)請求
- 沒了
正文開始
-
Retrofit是啥?
我想既然朋友你找到這篇文章堪唐,一定心里有個底巡语,簡單說就是一個簡化網(wǎng)絡(luò)操作的庫
-
準(zhǔn)備工作
1. 添加依賴
//這是Retrofit的包
compile 'com.squareup.retrofit2:retrofit:2.2.0'
//這是Retrofit用來將得到的json轉(zhuǎn)化成bean對象的包
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
2. 用于請求數(shù)據(jù)的api,這里送你一個
//最后面的num=3淮菠,這個數(shù)字可以自己改男公,需要幾條數(shù)據(jù)就寫幾
http://www.imooc.com/api/teacher?type=4&num=3
3. json對應(yīng)的javabean
咱們先將2中的url用瀏覽器訪問一下,會得到一串json字符串
根據(jù)json內(nèi)容自己敲一個bean
復(fù)制json字符串兜材,然后去jsonschema2pojo將他轉(zhuǎn)化成一個bean
下載之后你得到了:Bean.java和Datum.java兩個源文件
/**Bean.java**/
public class Bean {
public Integer status;
public List<Datum> data = null;
public String msg;
private Map<String, Object> additionalProperties = new HashMap<>();
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
/**Datum.java**/
public class Datum {
public Integer id;
public String name;
public String picSmall;
public String picBig;
public String description;
public Integer learner;
private Map<String, Object> additionalProperties = new HashMap<>();
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
接下來你需要將他們復(fù)制到你項目的包下理澎,因為你要用到他們
至此,準(zhǔn)備就工作就全部做完了
-
正式開始使用Retrofit
1. 首先需要寫一個接口
這個接口規(guī)定get曙寡、post請求的url參數(shù)糠爬;規(guī)定一個返回Call對象(這個call對象用于正式發(fā)起請求并獲得返回數(shù)據(jù))的方法,這個方法接收的參數(shù)為url參數(shù)值举庶,用開始給的url舉例:
http://www.imooc.com/api/teacher?type=4&num=3
//num=3,num是一個參數(shù)执隧,3是參數(shù)值,而這個接口內(nèi)就規(guī)定了url中有哪些參數(shù)
//返回Call對象 的方法 接收的參數(shù)户侥,就是url的參數(shù)值
那么對于這個api镀琉,我們需要寫的接口應(yīng)該是這樣:
public interface ApiService {
@GET("teacher?type=4")
Call<Bean> getCall(@Query("num") int count);
}
//這個"@GET"是Retrofit的注解,表示進行g(shù)et請求蕊唐,()括號內(nèi)的字符串就是url的*參數(shù)信息*
//那為什么"&num=3"不見了呢屋摔?看官請看我下面...
//-------Call<Bean> getCall(@Query("num") int count);-------
//這個方法返回一個Call<Bean>對象,等會兒正式發(fā)起請求并獲取數(shù)據(jù)就靠他了
//對頭替梨,Bean就對應(yīng)于Bean.java钓试!因為我們需要解析json變成一個Bean實例嘛
//(@Query("num") int count)就厲害了装黑,他表示:
//在@GET("teacher?type=4")之中的字符串的后面,再添加"&num="
//那么num等于多少呢弓熏,這就在使用getCall方法的時候由參數(shù)int count決定了
好了恋谭,一個進行g(shù)et請求的接口就寫完了,也就這么兩行挽鞠,太簡單了疚颊!
其實,在這里還有另外一種情況信认,如果url不是在后面&添加參數(shù)材义,而需要指定的變量在url的路徑中呢?比如github這個api:
https://api.github.com/users/{user}/repos
{user}是需要查找的用戶名
這個時候接口就應(yīng)該這樣寫:
public interface ApiService {
@GET("users/{user}/repos")
Call<Bean> getCall(@Path("user") String u);
}
//{user}直接理解為一個變量,這個變量的值由↓決定
//@Path("user")表示將以上路徑中的{user}變量賦值為參數(shù)u的值
//當(dāng)然切記狮杨,這里的Call<Bean>的Bean應(yīng)該換成另外你根據(jù)API返回的json生成的bean
以上內(nèi)容母截,請另外嘗試,與本次demo無關(guān)呀
什么橄教?post請求的接口該怎么寫清寇?
**我也不知道(/▽╲)**
2. 接下來創(chuàng)建一個Retrofit實例,通過Retrofit實例創(chuàng)建 接口的實例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.imooc.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
//機智护蝶,就是通過baseUrl補全整個url信息了华烟!是不是上面@GET中殘缺url的疑惑一下就解決了?持灰!
//當(dāng)然在剛剛的接口中盔夜,你也可以一次性寫全url,但是這樣就不夠靈活了堤魁!
//----------------addConverterFactory(GsonConverterFactory.create())
//這一句規(guī)定解析json用哪個庫喂链,這就是最開始要你導(dǎo)入Gson庫的原因啦,咱們用Gson解析json
//當(dāng)然你也可以用其他的庫解析json妥泉,比如jackson椭微,寫法是一樣的,注意引入別人的庫就是了
//然后很完美的創(chuàng)建了一個retrofit實例盲链,并且通過retrofit實例來創(chuàng)建了一個接口的實例
3. 緊接著我們需要一個Call實例來正式的發(fā)起請求獲取數(shù)據(jù)
//請求3條數(shù)據(jù)蝇率,最后url就拼接成了最頂上給的url,是一毛一樣的
//沒錯刽沾,網(wǎng)絡(luò)請求有異常本慕,得try/catch一下
Call<Bean> call = apiService.getCall(3);
try {
call.execute();//執(zhí)行call,也就是正式發(fā)起網(wǎng)絡(luò)請求咯侧漓!
} catch (IOException e) {
e.printStackTrace();
}
那么問題來了锅尘,發(fā)起網(wǎng)絡(luò)請求之后,我去哪兒得到數(shù)據(jù)呢布蔗!機智的我把鼠標(biāo)放在"execute()"上鉴象,然后按下ctrl鍵:
原來call.execute()直接返回了一個請求結(jié)果忙菠,那么我們拿到這個結(jié)果來看看都有啥:
Response<Bean> response= call.execute();
result.//看下圖
哇何鸡,這么多方法纺弊,返回的都是什么?其實一看方法名和返回類型便知骡男,這里我們挑兩個打印出來看看:
try {
Response<Bean> response= call.execute();
Log.i(TAG, "response.body()----->" + response.body());
Log.i(TAG, "response.message()----->" + response.message());
Log.i(TAG, "response.code()----->" + response.code());
//明明打印了3個O巍!
} catch (IOException e) {
e.printStackTrace();
}
-
拿到返回結(jié)果之后
好的隔盛,現(xiàn)在所有代碼如下:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public interface ApiService {
@GET("teacher?type=4")
Call<Bean> getCall(@Query("num") int count);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.imooc.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
Call<Bean> call = apiService.getCall(3);
try {
Response<Bean> response= call.execute();
Log.i(TAG, "response.body()----->" + response.body());
Log.i(TAG, "response.message()----->" + response.message());
Log.i(TAG, "response.code()----->" + response.code());
} catch (IOException e) {
e.printStackTrace();
}
}
}
好像很完美了犹菱,馬上就能收獲利用retrofit發(fā)起網(wǎng)絡(luò)請求獲得數(shù)據(jù)的喜悅了!
來吮炕,Run起來腊脱!
------------別Run了,你的結(jié)果一定是:
因為你沒有添加網(wǎng)絡(luò)權(quán)限A住陕凹!
<uses-permission android:name="android.permission.INTERNET" />
好,這下OK了鳄炉,這次我們真正的Run起來杜耙!
報錯信息:
//這尼瑪我怎么在主線程進行網(wǎng)絡(luò)請求了呢!拂盯!
Caused by: android.os.NetworkOnMainThreadException
好了佑女,這下要真正的解決問題了!真正的所有代碼MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public interface ApiService {
@GET("teacher?type=4")
Call<Bean> getCall(@Query("num") int count);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.imooc.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
final Call<Bean> call = apiService.getCall(3);
//----這里直接new了一個子線程來進行網(wǎng)絡(luò)請求谈竿,看下方有一個Retrofit自帶的異步請求方法
new Thread(new Runnable() {
@Override
public void run() {
try {
Response<Bean> response= call.execute();
Log.i(TAG, "response.body()----->" + response.body());
Log.i(TAG, "response.message()----->" + response.message());
Log.i(TAG, "response.code()----->" + response.code());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//如果你選擇了這種寫法
//可千萬別忘了start()!不然等會兒看不到log团驱,你又要拿起砍刀找我了!
//-------------------------------------
}
Retrofit還有一個本身就是異步請求的方法:
//call.enqueue()方法接收一個Callback回調(diào)空凸,我們直接new出來嚎花,這是異步請求方法
call.enqueue(new Callback<Bean>() {
@Override
public void onResponse(Call<Bean> call, Response<Bean> response) {
//當(dāng)獲取到返回結(jié)果的時候回調(diào)這個方法
Log.i(TAG, "response.body()----->" + response.body());
Log.i(TAG, "response.message()----->" + response.message());
Log.i(TAG, "response.code()----->" + response.code());
}
@Override
public void onFailure(Call<Bean> call, Throwable t) {
//網(wǎng)絡(luò)請求失敗的時候回調(diào)這個方法
}
});
把上面的上面的new Thread(......).start();全部換成上面的代碼,也一樣OK了劫恒!
- 當(dāng)然更推薦這里寫法了贩幻!
好了,廢話這么多两嘴,來看看log到底打印出來了一些什么吧:
真的太完美了丛楚,這個結(jié)果告訴我們請求碼是200,請求信息是OK憔辫,還給了我一個Bean對象趣些!
噢對了,看看我會不會拿到一個假的Bean對象贰您!眼見為實
......
Bean b = response.body();
Log.i(TAG, "Bean內(nèi)容:" + b.msg);
Log.i(TAG, "Bean內(nèi)容:" + b.data.get(0).description);
......
好了坏平,至此我們已經(jīng)成功利用Retrofit進行網(wǎng)絡(luò)請求拢操,并且將得到的json直接變成了Bean對象,簡直不要太爽
- 如果我的文章確實有幫助到你舶替,請不要忘了點一下文末的"?"讓他變成"?"
- 作為新手難免很多地方理解不到位令境,文中若有錯誤請直(bu)接(yao)指(ma)出(wo)
- 寫作不易!