前言
Retrofit是一個RESTful的網(wǎng)絡(luò)請求框架的一種封裝坟瓢,Retrofit只需要對網(wǎng)絡(luò)請求信息進(jìn)行封裝操禀,然后通過內(nèi)置的OkHttp進(jìn)行網(wǎng)絡(luò)請求褂策,當(dāng)從服務(wù)器返回數(shù)據(jù)之后,OkHttp將結(jié)果交給Retrofit,Retrofit根據(jù)用戶的需求對結(jié)果進(jìn)行解析斤寂,這篇文章我用一個簡單的栗子去認(rèn)識并使用Retrofit蔑水。栗子是請求網(wǎng)絡(luò)獲取快遞信息,旨在初識并使用扬蕊,并未深入。
前期準(zhǔn)備
要使用Retrofit首先要在build.gradle添加依賴
compile 'com.squareup.retrofit2:retrofit:2.1.0'
Retrofit 2.0之后也不再依賴于Gson 丹擎,所以我們要想解析json只能自己添加Gson Converter依賴
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
然后聯(lián)網(wǎng)別忘了在清單文件添加權(quán)限
<uses-permission android:name="android.permission.INTERNET" />
請求的接口為:
http://www.kuaidi100.com/query?type=快遞公司代號&postid=快遞單號
快遞公司代號為:申通=”shentong” EMS=”ems” 順豐=”shunfeng” 圓通=”yuantong” 中通=”zhongtong” 韻達(dá)=”yunda” 天天=”tiantian” 匯通=”huitongkuaidi” 全峰=”quanfengkuaidi” 德邦=”debangwuliu” 宅急送=”zhaijisong”
前期編碼
下面一步步完成這個例子尾抑,我是打算用listview去顯示這些數(shù)據(jù),所以界面就直接是listview跟一個出錯時顯示的文字
界面布局為:
<?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.sjr.helloretrofit.MainActivity">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/tv_erro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="16sp"
android:visibility="gone" />
</RelativeLayout>
listviewitem布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/tv_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:lines="2"
android:singleLine="true"
android:text="address"
android:textColor="#A7A3A7"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:text="time"
android:textColor="#A7A3A7"
android:textSize="16sp" />
</LinearLayout>
然后編寫實體bean蒂培,實體bean可以直接用GsonFormat生成再愈,這里就不在累贅敘述
由于listview用得實在是太頻繁了,所以我老早就封裝好他的適配器了护戳,下面是適配器代碼翎冲,可以直接拷貝當(dāng)做工具類來用..
/**
*
* ListView適配器基類
*/
public abstract class MyListViewBaseAdapter<T> extends BaseAdapter {
private Context context;
private List<T> datas;
private int resId;
public MyListViewBaseAdapter(Context context, int resId) {
this.context = context;
this.resId = resId;
datas = new ArrayList<>();
}
/**
* @param datas 設(shè)置數(shù)據(jù)源數(shù)據(jù)
*/
public void setDatas(List<T> datas) {
this.datas = datas;
notifyDataSetChanged();
}
/**
* 增加數(shù)據(jù)
* @param datas
*/
public void addDatas(List<T> datas) {
this.datas.addAll(datas);
notifyDataSetChanged();
}
@Override
public int getCount() {
return datas == null ? 0 : datas.size();
}
@Override
public Object getItem(int position) {
return datas == null ? 0 :datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(context, resId, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
bindDatas(holder, datas.get(position));
return convertView;
}
public abstract void bindDatas(ViewHolder holder, T datas);
public class ViewHolder {
public Map<Integer, View> mapCache = new HashMap<>();
public View layoutView;//布局對象
public ViewHolder(View layoutView) {
this.layoutView = layoutView;
}
public View getView(int viewId) {
if (mapCache.get(viewId) != null) {
return mapCache.get(viewId);
} else {
View v = layoutView.findViewById(viewId);
mapCache.put(viewId, v);
return v;
}
}
}
}
然后只要后面的listview適配器繼承即可,下面是這個栗子的listview適配器:
public class ListViewAdapter extends MyListViewBaseAdapter<ExpressBean.DataBean> {
public ListViewAdapter(Context context, int resId) {
super(context, resId);
}
@Override
public void bindDatas(ViewHolder holder, ExpressBean.DataBean datas) {
TextView tvAddress = (TextView) holder.getView(R.id.tv_address);
tvAddress.setText(datas.getContext());
TextView tvTime = (TextView) holder.getView(R.id.tv_time);
tvTime.setText(datas.getTime());
}
}
Hello Retrofit
寫完上面那些前期準(zhǔn)備的代碼就可以著手編寫Retrofit的邏輯代碼了首先根據(jù)快遞接口編寫Service
/**
* Created by 宋家任 on 2016/9/9.
* 快遞業(yè)務(wù)接口
*/
public interface ExpressApiService {
@GET("query")
Call<ExpressBean> getExpressInfo(@Query("type") String name,
@Query("postid") long id);
}
其實@GET注解表示get請求媳荒,@Query表示請求參數(shù)抗悍,根據(jù)接口我們知道是根據(jù)type和postid兩個參數(shù)請求。
然后就可以開始請求數(shù)據(jù)了钳枕,邏輯代碼為:
public class MainActivity extends AppCompatActivity {
private static final String BASEURL = "http://www.kuaidi100.com/";
@BindView(R.id.lv)
ListView lv;
@BindView(R.id.tv_erro)
TextView tvErro;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
downDatas();
}
private void downDatas() {
//創(chuàng)建Retrofit實例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASEURL)//固定的地址
.addConverterFactory(GsonConverterFactory.create())//添加轉(zhuǎn)換器工廠
.build();
ExpressApiService service = retrofit.create(ExpressApiService.class);
Call<ExpressBean> call = service.getExpressInfo("tiantian", 666798482392L);
//異步請求網(wǎng)絡(luò)缴渊,同步為execute
call.enqueue(new Callback<ExpressBean>() {
@Override
public void onResponse(Call<ExpressBean> call, Response<ExpressBean> response) {
if ("200".equals(response.body().getStatus())) {
List<ExpressBean.DataBean> beans = response.body().getData();
ListViewAdapter adapter = new ListViewAdapter(MainActivity.this, R.layout.item_lv);
lv.setAdapter(adapter);
adapter.setDatas(beans);
} else {
tvErro.setVisibility(View.VISIBLE);
tvErro.setText("no message");
}
}
@Override
public void onFailure(Call<ExpressBean> call, Throwable t) {
tvErro.setVisibility(View.VISIBLE);
tvErro.setText(t.getMessage());
}
});
}
}
其中
Call<ExpressBean> call = service.getExpressInfo("tiantian", 666798482392L);
Call是Retrofit用來進(jìn)行網(wǎng)絡(luò)請求并處理返回結(jié)果的類,請求很簡單鱼炒,只要把要請求的參數(shù)傳遞給Call即可.
最后效果如下:
總結(jié)
Retrofit這個庫很優(yōu)秀衔沼,關(guān)于它還有各種細(xì)節(jié)值得剖析,但是這篇文章的目的只是讓沒接觸過Retrofit的同學(xué)進(jìn)行了解使用昔瞧,后續(xù)我應(yīng)該會接著寫自己對它的深入理解指蚁。
Demo下載地址:http://download.csdn.net/detail/lxzmmd/9628114