Retrofit2.0 使用教程——MVP查快遞

使用準(zhǔn)備

  • build.gradle中配置引用

    implementation 'com.squareup.retrofit2:retrofit:2.6.2'
    implementation 'com.google.code.gson:gson:2.8.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
    

    需要導(dǎo)入的包除了retrofit外還需要導(dǎo)入gson用來(lái)轉(zhuǎn)化json數(shù)據(jù)蕴茴,導(dǎo)入converter-gson來(lái)使gson可以和retrofit配套使用恭应。

    這里是三個(gè)包的git地址所踊,用的時(shí)候可以從這里引用最新的包和獲取文檔支持:

    retrofit gson converter-gson

  • 加入網(wǎng)絡(luò)權(quán)限

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    

建立數(shù)據(jù)模型

我們這里使用的是Gson解析,需要事先和接口約定好對(duì)應(yīng)的json樣式,然后在本地寫(xiě)好對(duì)應(yīng)的數(shù)據(jù)模型曹质。這里以快遞100的返回?cái)?shù)據(jù)為例,可以構(gòu)造如下模型:

public class ExpressBean {
    public String message;
    public String nu;
    public String ischeck;
    public String com;
    public String status;
    public String condition;
    public String state;
    public List<DataBean> data;
    public static class DataBean {
        public String time;
        public String context;
        public String ftime;
    }
}

在構(gòu)建本地?cái)?shù)據(jù)模型時(shí),我推薦一個(gè)好用的插件妇穴,可以一鍵轉(zhuǎn)化json數(shù)據(jù)為java類:

GsonFormat

網(wǎng)絡(luò)接口設(shè)置

retrofit的請(qǐng)求是通過(guò)接口加注解的形式來(lái)實(shí)現(xiàn)的,這里我寫(xiě)了個(gè)查詢圓通快遞的簡(jiǎn)單例子:

public interface ExpressQuestionService {
    @GET("query?type=yuantong")
    Call<ExpressBean> queryExpress(@Query("postid") String expressCode);
}

這個(gè)方法在調(diào)用后隶债,會(huì)拼接postid到請(qǐng)求的后面腾它,組成query?type=yuantong&postid=expressCode;

搭建mvp接口

MVP的第一步就是寫(xiě)接口,接口書(shū)寫(xiě)的過(guò)程也就是流程梳理的過(guò)程死讹,當(dāng)接口書(shū)寫(xiě)完后携狭,只需要依次填補(bǔ)各個(gè)實(shí)現(xiàn)類就完成了,我們這個(gè)小需求很簡(jiǎn)單回俐,所以接口也不復(fù)雜逛腿。

這里我把三個(gè) 接口放到一起稀并,方便調(diào)整。

public interface ExpressQueryContract {
    interface View {
        /**
         * 綁定返回?cái)?shù)據(jù)到頁(yè)面
         */
        void bindView(ExpressBean bean);

        /**
         * 顯示提示信息
         */
        void showToast(String message);
    }

    interface Presenter {
        /**
         * 處理查詢邏輯
         */
        void queryExpress(String expressCode);
    }

    interface Model {
        /**
         * 調(diào)用接口查詢信息
         */
        void queryExpress(String expressCode, Callback<ExpressBean> callback);
    }
}

實(shí)現(xiàn)MVP接口

接口定義好了单默,接下來(lái)依次寫(xiě)各個(gè)接口的實(shí)現(xiàn)類就好了

  • 實(shí)現(xiàn)Model

    public class ExpressQueryModel implements ExpressQueryContract.Model {
        @Override
        public void queryExpress(String expressCode, Callback<ExpressBean> callback) {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://www.kuaidi100.com/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            ExpressQuestionService service = retrofit.create(ExpressQuestionService.class);
            Call<ExpressBean> repos = service.queryExpress(expressCode);
            repos.enqueue(callback);
        }
    }
    
  • 實(shí)現(xiàn)Presenter

    public class ExpressQueryPresenter implements ExpressQueryContract.Presenter {
        private ExpressQueryContract.View view;
        private ExpressQueryContract.Model model;
    
        public ExpressQueryPresenter(ExpressQueryContract.View view) {
            this.view = view;
            model = new ExpressQueryModel();
        }
    
        @Override
        public void queryExpress(String expressCode) {
            model.queryExpress(expressCode, new Callback<ExpressBean>() {
                @Override
                public void onResponse(Call<ExpressBean> call, Response<ExpressBean> response) {
                    if (response != null && response.body() != null) {
                        view.bindView(response.body());
                    } else {
                        onFailure(null, null);
                    }
                }
    
                @Override
                public void onFailure(Call<ExpressBean> call, Throwable t) {
                    if (t != null && t.getMessage() != null) {
                        view.showToast(t.getMessage());
                    } else {
                        view.showToast("槽糕,服務(wù)開(kāi)小差了,稍后再試吧");
                    }
                }
            });
        }
    }
    
  • 實(shí)現(xiàn)View

    public class ExpressQuestionActivity extends AppCompatActivity implements ExpressQueryContract.View {
        private Button button;
        private TextView textView;
        private EditText editText;
        private ExpressQueryContract.Presenter presenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_express_question);
            findView();
            presenter = new ExpressQueryPresenter(this);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (TextUtils.isEmpty(getExpressCode())) {
                        showToast("單號(hào)不能為空");
                    } else {
                        presenter.queryExpress(getExpressCode());
                    }
                }
            });
        }
    
        private String getExpressCode() {
            String code = editText.getText().toString().trim();
            return code;
        }
    
        private void findView() {
            button = findViewById(R.id.button_get);
            textView = findViewById(R.id.net_result);
            editText = findViewById(R.id.express_code);
        }
    
        @Override
        public void bindView(ExpressBean bean) {
            textView.setText(bean.toString());
        }
    
        @Override
        public void showToast(String message) {
            Toast.makeText(this, message, Toast.LENGTH_LONG);
        }
    }
    
  • 總體包結(jié)構(gòu)

在這里插入圖片描述

可能遇到的問(wèn)題

  • IllegalArgumentException

    運(yùn)行時(shí)出現(xiàn)如下異常信息:

    java.lang.IllegalArgumentException: Unable to create converter for class ****

    這類異常是由于沒(méi)有添加對(duì)應(yīng)的ConverterFactory造成的碘举,retrofit必須配套對(duì)應(yīng)的類型解析器才能使用,具體的代碼就是下面的第三行語(yǔ)句

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://www.kuaidi100.com/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    
  • CLEARTEXT

    請(qǐng)求一直失敗搁廓,直接走onFailure回調(diào)引颈,錯(cuò)誤信息類似下面這樣:

    CLEARTEXT communication to www.kuaidi100.com not permitted by network security policy

    這是由于android9.0開(kāi)始,對(duì)http請(qǐng)求的限制造成的境蜕,具體的解決方法可以參考這篇文章Android9.0 http網(wǎng)絡(luò)請(qǐng)求解決方案

總結(jié)

好了蝙场,結(jié)束。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末粱年,一起剝皮案震驚了整個(gè)濱河市售滤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌台诗,老刑警劉巖完箩,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拉队,居然都是意外死亡弊知,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)粱快,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)秩彤,“玉大人,你說(shuō)我怎么就攤上這事事哭∧盘颍” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵慷蠕,是天一觀的道長(zhǎng)珊拼。 經(jīng)常有香客問(wèn)我,道長(zhǎng)流炕,這世上最難降的妖魔是什么澎现? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮每辟,結(jié)果婚禮上剑辫,老公的妹妹穿的比我還像新娘。我一直安慰自己渠欺,他們只是感情好符欠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布浇借。 她就那樣靜靜地躺著拉一,像睡著了一般田柔。 火紅的嫁衣襯著肌膚如雪渐裸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼掌测。 笑死,一個(gè)胖子當(dāng)著我的面吹牛产园,可吹牛的內(nèi)容都是我干的汞斧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼什燕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粘勒!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起屎即,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庙睡,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后剑勾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體埃撵,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赵颅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年虽另,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饺谬。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捂刺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出募寨,到底是詐尸還是另有隱情族展,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布拔鹰,位于F島的核電站仪缸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏列肢。R本人自食惡果不足惜恰画,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓷马。 院中可真熱鬧拴还,春花似錦、人聲如沸欧聘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至费封,卻和暖如春焕妙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孝偎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工访敌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衣盾。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓寺旺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親势决。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阻塑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容