首页  »   Android

Android 鏁欎綘涓€姝ユ鎼徐MVP+Retrofit+RxJava缃戠粶璇锋眰妗嗘灦

网友分享于:2018-05-19  浏览:0次
Android 鏁欎綘涓€姝ユ鎼缓MVP+Retrofit+RxJava缃戠粶璇锋眰妗嗘灦

1.浠€涔堟槸MVP锛?/span>

MVP锛圡odel View Presenter锛夊叾瀹炲氨鏄竴绉嶉」鐩殑鏁翠綋妗嗘灦锛岃兘璁╀綘鐨勪唬鐮佸彉寰楁洿鍔犵畝娲侊紝璇磋捣妗嗘灦澶у鍙兘杩樹細鎯冲埌MVC銆丮VVM銆傜敱浜庣瘒骞呭師鍥狅紝杩欓噷鎴戜滑鍏堜笉璁睲VVM锛屽厛鏉ョ湅涓€涓婱VC銆傚叾瀹濧ndroid鏈韩灏遍噰鐢ㄧ殑鏄疢VC锛圡odel View Controllor锛夋ā寮忋€佸叾涓璏odel鎸囩殑鏄暟鎹€昏緫鍜屽疄浣撴ā鍨嬶紱View鎸囩殑鏄竷灞€鏂囦欢銆丆ontrollor鎸囩殑鏄疉ctivity銆傚浜庡緢澶欰ndroid鍒濆鑰呭彲鑳戒細鏈夎繖鏍风殑缁忓巻锛屽啓浠g爜鐨勬椂鍊欙紝涓嶇涓変竷浜屽崄涓€閮藉線Activity涓啓锛屽綋鐒舵垜褰撳垵涔熸槸杩欎箞骞茬殑锛屾牴鏈氨娌℃湁浠€涔堟鏋剁殑姒傚康锛屽彧瑕佽兘瀹炵幇鏌愪竴涓姛鑳藉氨寰堝紑蹇冧簡锛屾病鏈夌杩欎箞澶氥€傚綋鐒堕」鐩瘮杈冨皬杩樺ソ锛屼竴鏃﹂」鐩瘮杈冨ぇ锛屼綘浼氬彂鐜帮紝Activity鎵€鎵挎媴鐨勪换鍔″叾瀹炴槸寰堥噸鐨勶紝瀹冩棦瑕佽礋璐i〉闈㈢殑灞曠ず鍜屼氦浜掞紝杩樺緱璐熻矗鏁版嵁鐨勮姹傚拰涓氬姟閫昏緫涔嬬被鐨勫伐浣滐紝鐩稿綋浜庢棦瑕佹墦鐞嗗搴紝鍙堣鏁欒偛鑷繁璋冪毊鐨勫瀛愶紝鐪熸槸鍙堝綋鐖瑰張褰撳銆傘€傘€傞偅璇ユ€庝箞鍔炲憿锛熻繖鏃跺€橮resenter杩欎釜缁х埗鏉ュ埌浜嗚繖涓搴€侾resenter瀵笰ctivity璇达紝鎴戞潵浜嗭紝浠ュ悗浣犲氨鍒繖涔堣緵鑻︿簡锛屼綘灏卞ソ濂芥墦鐞嗗ソView杩欎釜瀹讹紝鎴戜笓闂ㄦ潵璐熻矗鏁欒偛Model杩欏瀛愶紝鏈変粈涔堟儏鍐垫垜浼氬悜浣犲弽鏄犵殑銆傝繖鏃禔ctivity娴佷笅浜嗗垢绂忕殑鐪兼唱锛屼粠姝わ紝Model銆乂iew锛圓ctivity锛夈€丳resenter涓€瀹朵笁鍙h繃涓婁簡骞哥鐨勭敓娲汇€傘€傘€傚ソ浜嗙涓嵂缁х画锛岀敱浜嶱resenter锛堟垜浠嚜宸卞缓鐨勭被锛夌殑鍑虹幇锛屽彲浠ヤ娇View锛圓ctivity锛変笉鐢ㄧ洿鎺ュ拰Model鎵撲氦閬擄紝View锛圓ctivity锛夊彧鐢ㄨ礋璐i〉闈㈢殑鏄剧ず鍜屼氦浜掞紝鍓╀笅鐨勫拰Model浜や簰鐨勪簨鎯呴兘浜ょ粰Presenter鍋氾紝姣斿涓€浜涚綉缁滆姹傘€佹暟鎹殑鑾峰彇绛夛紝褰揚resenter鑾峰彇鍒版暟鎹悗鍐嶄氦缁橵iew锛圓ctivity锛夎繘琛屽睍绀猴紝杩欐牱锛孉ctivity鐨勪换鍔″氨澶уぇ鍑忓皬浜嗐€傝繖渚挎槸MVP锛圡odel 杩樻槸鎸囩殑鏁版嵁閫昏緫鍜屽疄浣撴ā鍨嬶紝View鎸囩殑鏄疉ctivity锛孭灏辨槸Presenter锛夋鏋剁殑宸ヤ綔鏂瑰紡銆?/div>
2.浠€涔堟槸Retrofit锛?/span>
鎺ヤ笅鏉ユ垜浠湅涓€涓嬩粈涔堟槸Retrofit銆傚湪瀹樼綉瀵筊etrofit鐨勬弿杩版槸杩欐牱鐨?br>A type-safe HTTP client for Android and Java璇翠汉璇濆氨鏄€滀竴涓被鍨嬪畨鍏ㄧ殑鐢ㄤ簬Android鍜孞ava缃戠粶璇锋眰鐨勫鎴风鈥濓紝鍏跺疄灏辨槸涓€涓皝瑁呭ソ鐨勭綉缁滆姹傚簱銆傛帴涓嬫潵灏辨潵鐪嬩竴涓嬭繖涓簱璇ユ€庝箞鐢ㄣ€傞鍏堟垜鍦ㄧ綉涓婃壘浜嗕竴涓狝PI鎺ュ彛鐢ㄤ簬娴嬭瘯锛?code>https://api.douban.com/v2/book/search?q=閲戠摱姊?amp;tag=&start=0&count=1杩欐槸涓€涓敤浜庢煡璇竴鏈功璇︾粏淇℃伅鐨勪竴涓姹傛帴鍙c€傚鏋滅洿鎺ョ敤娴忚鍣ㄦ墦寮€鐨勮瘽浼氳繑鍥炰互涓嬪唴瀹癸細
鎺ヤ笅鏉ユ垜浠潵鐪嬬湅濡備綍鐢≧etrofit灏嗕笂闈㈢殑璇锋眰涓嬫潵銆備负浜嗗湪Android Studio涓坊鍔燫etrofit搴擄紝鎴戜滑闇€瑕佹坊鍔犲涓嬩緷璧栵細
compile 'com.squareup.retrofit2:retrofit:2.1.0'

濂戒簡锛屾坊鍔犲畬璇ュ簱锛屾垜浠啀鏉ョ湅鐪嬪浣曚娇鐢紝棣栧厛鎴戜滑鏉ュ缓涓€涓疄浣撶被Book锛岀敤浜庤缃戠粶璇锋眰鍚庤繑鍥炵殑鏁版嵁銆傝繖閲岄『甯﹁涓€涓嬶紝鏈夌殑浜哄缓涓€涓疄浣撶被鏃跺彲鑳戒細鏍规嵁娴忚鍣ㄤ腑杩斿洖涓殑鏁版嵁涓€琛屼竴琛屾暡锛屽叾瀹炶繖鏍烽潪甯搁夯鐑︼紝杩欓噷鏁欏ぇ瀹朵竴涓畝鍗曠殑鏂规硶锛岀灛闂寸敓鎴愪竴涓疄浣撶被銆傛病閿欐湁鐨勪汉鍙兘鐢ㄨ繃锛屾垜浠渶瑕佷竴涓彃浠?code>GsonFormat銆傚畠鐨勪娇鐢ㄤ篃寰堢畝鍗曪紝棣栧厛闇€瑕佸湪Android Studio涓笅杞斤紝鐐瑰嚮宸︿笂瑙掕彍鍗曟爮涓殑File,鐒跺悗鐐瑰嚮Settings锛屽湪寮圭獥涓€夋嫨Plugins,鐒跺悗鐐瑰嚮涓嬫柟鐨?code>Browse repositories...


鐒跺悗鍦ㄦ柊鎵撳紑鐨勭獥鍙d腑鎼滅储GsonFormat锛岀偣鍑诲彸渚х豢鑹叉寜閽氨鍙互涓嬭浇瀹夎浜嗭紝瀹夎瀹岄渶瑕侀噸鍚笅studio锛屽氨鍙互鐢ㄤ簡銆?/p>


瀹冪殑鐢ㄦ硶涔熷緢绠€鍗曪紝姣斿浣犲厛寤虹珛涓€涓柊鐨勭┖绫诲彇鍚岯ook锛岀劧鍚庡湪閲岄潰鎸?code>Alt+insert,浼氭湁涓皬寮圭獥閫夋嫨GsonFormat,涔嬪悗鍦ㄥ脊鍑虹殑缂栬緫妗嗕腑鎷峰叆鍦ㄦ祻瑙堝櫒涓姹備笅鏉ョ殑閭d竴鍧ㄤ笢瑗匡紝鐒跺悗涓€鐩寸偣ok灏变細鑷姩鐢熸垚瀛楁锛屼互鍙妔et鍜実et鏂规硶锛屼竴浼氬効鎴戜滑鐢≧etrofit璇锋眰涓嬫潵鐨勬暟鎹兘浼氫繚瀛樺湪杩欎釜瀹炰綋绫讳腑锛岃繕鏄尯鏂逛究鐨勩€傛渶鍚庢垜浠噷闈㈡坊鍔犱竴涓猼oString()鏂规硶锛岀敤浜庡悗闈㈡樉绀烘柟渚裤€?/p>

鎺ヤ笅鏉ワ紝鍥炲埌鎴戜滑鐨凴etrofit涓笂锛屽疄浣撶被宸茬粡寤哄ソ浜嗭紝鎴戜滑鏉ョ湅鐪嬭繖涓猂etrofit濡備綍杩涜缃戠粶璇锋眰锛屽叾瀹炰唬鐮佷篃寰堢畝鍗曘€傞鍏堟垜浠渶瑕佸畾涔変竴涓帴鍙o紝鍙栧悕RetrofitService 锛?/span>
public interface RetrofitService {
    @GET("book/search")
    Call<Book> getSearchBook(@Query("q") String name, 
                             @Query("tag") String tag, 
                             @Query("start") int start, 
                             @Query("count") int count);
}

浣滆€咃細铔囧彂濂冲
閾炬帴锛歨ttp://www.jianshu.com/p/7b839b7c5884
渚嗘簮锛氱畝涔?
钁椾綔鏉冨綊浣滆€呮墍鏈夈€傚晢涓氳浆杞借鑱旂郴浣滆€呰幏寰楁巿鏉冿紝闈炲晢涓氳浆杞借娉ㄦ槑鍑哄銆?/pre>
getSearchBook锛岄偅涔堣繖涓柟娉曟槸鍋氫粈涔堢殑鍛紵鍏跺疄瀹冨共鐨勪簨寰堢畝鍗曪紝灏辨槸鎷兼帴涓€涓猆RL鐒跺悗杩涜缃戠粶璇锋眰銆傝繖閲屾垜浠嫾鎺ョ殑URL灏辨槸涓婃枃鎻愬埌鐨勬祴璇昒RL:https://api.douban.com/v2/book/search?q=閲戠摱姊?amp;tag=&start=0&count=1銆傝仾鏄庣殑浣犱竴瀹氱湅鍑烘潵浜嗭紝鍦ㄨ繖涓猆RL涓璪ook/search灏辨槸GET鍚庣殑鍊硷紝鑰?鍚庣殑q銆乼ag銆乻tart銆乧ount绛夊叆鍙傚氨鏄繖涓柟娉曠殑鍏ュ弬銆傛湁鐨勬湅鍙嬪彲鑳借闂簡锛?/span>https://api.douban.com/v2/杩欎箞涓€澶т覆璺戝摢鍘讳簡锛熷叾瀹炴垜浠湪杩涜缃戠粶璇锋眰鏃讹紝鍦║RL涓墠涓€閮ㄥ垎鏄浉瀵逛笉鍙樼殑銆備粈涔堟剰鎬濆憿锛屾瘮濡備綘鎵撳紑闂翠功缃戠珯锛屽湪闂翠功涓綘鎵撳紑涓嶅悓鐨勭綉椤碉紝铏界劧瀹冪殑URL涓嶅悓锛屼絾浣犱細鍙戠幇锛屾瘡涓猆RL鍓嶉潰閮芥槸浠?/span>http://www.jianshu.com/寮€澶?鎴戜滑鎶婅繖涓笉鍙樼殑閮ㄥ垎锛屼篃鍙仛baseUrl鎻愬嚭鏉ワ紝鏀惧埌鍙︿竴涓湴鏂?鍦ㄤ笅闈㈡垜浠細鎻愬埌銆傝繖鏍锋垜浠竴涓畬鏁寸殑URL灏辨嫾鎺ュソ浜嗐€傚湪鏂规硶鐨勫紑澶存垜浠彲浠ョ湅鍒版湁涓狦ET鐨勬敞閲婏紝璇存槑杩欎釜璇锋眰鏄疓ET鏂规硶锛屽綋鐒朵綘涔熷彲浠ユ牴鎹叿浣撻渶瑕佺敤POST銆丳UT銆丏ELETE浠ュ強HEAD銆備粬浠殑鍖哄埆濡備笅锛?/span>
  • GET ----------鏌ユ壘璧勬簮锛堟煡锛?/li>
  • POST --------淇敼璧勬簮锛堟敼锛?/li>
  • PUT ----------涓婁紶鏂囦欢锛堝锛?/li>
  • DELETE ----鍒犻櫎鏂囦欢锛堝垹锛?/li>
  • HEAD--------鍙姹傞〉闈㈢殑棣栭儴

鐒跺悗鎴戜滑鏉ョ湅涓€涓嬭繖涓柟娉曠殑杩斿洖鍊硷紝瀹冭繑鍥濩all瀹炰綋锛屼竴浼氭垜浠鐢ㄥ畠杩涜鍏蜂綋鐨勭綉缁滆姹傦紝鎴戜滑闇€瑕佷负瀹冩寚瀹氭硾鍨嬩负Book涔熷氨鏄垜浠暟鎹殑瀹炰綋绫汇€傛帴涓嬫潵锛屼綘浼氬彂鐜拌繖涓柟娉曠殑鍏ュ弬鍜屾垜浠钩鏃舵柟娉曠殑鍏ュ弬杩樹笉澶т竴鏍枫€傚湪姣忎釜鍏ュ弬鍓嶈繕澶氫簡涓€涓敞瑙c€傛瘮濡傜涓€涓叆鍙?code>@Query("q") String name锛?code>Query琛ㄧず鎶婁綘浼犲叆鐨勫瓧娈垫嫾鎺ヨ捣鏉ワ紝姣斿鍦ㄦ祴璇晆rl涓垜浠彲浠ョ湅鍒?code>q=閲戠摱姊?/code>鐨勫叆鍙傦紝閭d箞Query鍚庨潰鐨勫€煎繀椤绘槸q锛岃鍜寀rl涓繚鎸佷笉鍙橈紝鐒跺悗鎴戜滑瀹氫箟浜哠tring绫诲瀷鐨刵ame锛屽綋璋冪敤杩欎釜鏂规硶鏄紝鐢ㄤ簬浼犲叆瀛楃涓诧紝姣斿鍙互浼犲叆鈥滈噾鐡舵鈥濄€傞偅涔堣繖涓柟娉曞氨浼氳嚜鍔ㄥ湪q鍚庨潰鎷间笂杩欎釜瀛楃涓茶繘琛岀綉缁滆姹傘€備互姝ょ被鎺紝杩欎釜url闇€瑕佸嚑涓叆鍙備綘灏卞湪杩欎釜鏂规硶涓畾涔夊嚑涓叆鍙傦紝姣忎釜鍏ュ弬鍓嶉兘瑕佸姞涓?code>Query娉ㄨВ銆傚綋鐒禦etrofit闄や簡Query杩欎釜娉ㄨВ澶栵紝杩樻湁鍏朵粬鍑犱釜姣斿锛欯QueryMap銆丂Path銆丂Body銆丂FormUrlEncoded/@Field銆丂Header/@Headers銆傛垜浠潵鐪嬩竴涓嬩粬浠殑鍖哄埆:

@Query(GET璇锋眰):

鐢ㄤ簬鍦╱rl鍚庢嫾鎺ヤ笂鍙傛暟锛屼緥濡傦細

@GET("book/search")
Call<Book> getSearchBook(@Query("q") String name);//name鐢辫皟鐢ㄨ€呬紶鍏?/code>

鐩稿綋浜庯細

@GET("book/search?q=name")
Call<Book> getSearchBook();

@QueryMap(GET璇锋眰):

褰撶劧濡傛灉鍏ュ弬姣旇緝澶氾紝灏卞彲浠ユ妸瀹冧滑閮芥斁鍦∕ap涓紝渚嬪锛?/p>

@GET("book/search")
Call<Book> getSearchBook(@QueryMap Map<String, String> options);

@Path(GET璇锋眰):

鐢ㄤ簬鏇挎崲url涓煇涓瓧娈碉紝渚嬪锛?/p>

@GET("group/{id}/users")
Call<Book> groupList(@Path("id") int groupId);

鍍忚繖绉嶈姹傛帴鍙o紝鍦╣roup鍜寀ser涔嬮棿鏈変釜涓嶇‘瀹氱殑id鍊奸渶瑕佷紶鍏ワ紝灏卞彲浠ヨ繖绉嶆柟娉曘€傛垜浠妸寰呭畾鐨勫€煎瓧娈电敤{}鎷捣鏉ワ紝褰撶劧 {}閲岀殑鍚嶅瓧涓嶄竴瀹氬氨鏄痠d锛屽彲浠ヤ换鍙栵紝浣嗛渶鍜?code>@Path鍚庢嫭鍙烽噷鐨勫悕瀛椾竴鏍枫€傚鏋滃湪user鍚庨潰杩橀渶瑕佷紶鍏ュ弬鏁扮殑璇濓紝灏卞彲浠ョ敤Query鎷兼帴涓婏紝姣斿锛?/p>

@GET("group/{id}/users")
Call<Book> groupList(@Path("id") int groupId,@Query("sort") String sort);

褰撴垜浠皟鐢ㄨ繖涓柟娉曟椂锛屽亣璁炬垜浠琯roupId浼犲叆1锛宻ort浼犲叆鈥?鈥濓紝閭d箞瀹冩嫾鎺ユ垚鐨剈rl灏辨槸group/1/users?sort=2锛屽綋鐒舵渶鍚庤姹傜殑璇濊繕浼氬姞涓婂墠闈㈢殑baseUrl銆?/p>

@Body(POST璇锋眰):

鍙互鎸囧畾涓€涓璞′綔涓篐TTP璇锋眰浣?姣斿锛?/p>

@POST("users/new")
Call<User> createUser(@Body User user);

瀹冧細鎶婃垜浠紶鍏ョ殑User瀹炰綋绫昏浆鎹负鐢ㄤ簬浼犺緭鐨凥TTP璇锋眰浣擄紝杩涜缃戠粶璇锋眰銆?/p>

@Field(POST璇锋眰):

鐢ㄤ簬浼犻€佽〃鍗曟暟鎹細

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);

娉ㄦ剰寮€澶村繀椤诲鍔犱笂@FormUrlEncoded杩欏彞娉ㄩ噴锛屼笉鐒朵細鎶ラ敊銆傝〃鍗曡嚜鐒舵槸鏈夊缁勯敭鍊煎缁勬垚锛岃繖閲岀殑first_name灏辨槸閿紝鑰屽叿浣撲紶鍏ョ殑first灏辨槸鍊煎暒銆?/p>

@Header/@Headers(POST璇锋眰):

鐢ㄤ簬娣诲姞璇锋眰澶撮儴锛?/p>

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

琛ㄧず灏嗗ご閮ˋuthorization灞炴€ц缃负浣犱紶鍏ョ殑authorization锛涘綋鐒朵綘杩樺彲浠ョ敤@Headers琛ㄧず,浣滅敤鏄竴鏍风殑姣斿锛?/p>

@Headers("Cache-Control: max-age=640000")
@GET("user")
Call<User> getUser()

褰撶劧浣犲彲浠ュ涓缃細

@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("user")
Call<User> getUser()

杩欐牱鎴戜滑灏辨妸涓婇潰杩欎釜RetrofitService 鎺ュ彛绫昏В閲婄殑宸笉澶氫簡銆傛垜瑙夊緱锛孯etrofit鏈€涓昏鐨勪篃灏辨槸杩欎釜鎺ュ彛绫荤殑瀹氫箟浜嗐€?/p>

鏈変簡杩欎釜鎺ュ彛绫伙紝鎴戜滑鏉ョ湅涓€涓嬶紝鍒板簳濡備綍浣跨敤杩欎釜鎴戜滑瀹氫箟鐨勬帴鍙f潵杩涜缃戠粶璇锋眰銆備唬鐮佸涓嬶細

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.douban.com/v2/")
        .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
        .build();
RetrofitService service = retrofit.create(RetrofitService.class);
Call<Book> call =  service.getSearchBook("閲戠摱姊?, null, 0, 1);
call.enqueue(new Callback<Book>() {
    @Override
    public void onResponse(Call<Book> call, Response<Book> response) {
        text.setText(response.body()+"");
    }
    @Override
    public void onFailure(Call<Book> call, Throwable t) {
    }
});

杩欓噷鎴戜滑鍙互鐪嬪埌锛屽厛鏂板缓浜嗕竴涓猂etrofit瀵硅薄锛岀劧鍚庣粰瀹冭缃竴涓垜浠墠闈㈣鐨刡aseUrlhttps://api.douban.com/v2/.鍥犱负鎺ュ彛杩斿洖鐨勬暟鎹笉鏄垜浠渶瑕佺殑瀹炰綋绫伙紝鎴戜滑闇€瑕佽皟鐢╝ddConverterFactory鏂规硶杩涜杞崲銆傜敱浜庤繑鍥炵殑鏁版嵁涓簀son绫诲瀷锛屾墍浠ュ湪杩欎釜鏂规硶涓紶鍏son杞崲宸ュ巶GsonConverterFactory.create(new GsonBuilder().create())锛岃繖閲屾垜浠渶瑕佸湪studio涓坊鍔燝son鐨勪緷璧栵細
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

鐒跺悗鎴戜滑璋冪敤retrofit鐨刢reate鏂规硶骞朵紶鍏ヤ笂闈㈡垜浠畾涔夌殑鎺ュ彛鐨勬枃浠跺悕RetrofitService.class锛屽氨鍙互寰楀埌RetrofitService 鐨勫疄浣撳璞°€傛湁浜嗚繖涓璞★紝鎴戜滑灏卞彲浠ヨ皟鐢ㄩ噷闈箣鍓嶅畾涔夊ソ鐨勮姹傛柟娉曚簡銆傛瘮濡傦細

Call<Book> call =  service.getSearchBook("閲戠摱姊?, null, 0, 1);

瀹冧細杩斿洖涓€涓狢all瀹炰綋绫伙紝鐒跺悗灏卞彲浠ヨ皟鐢–all鐨別nqueue鏂规硶杩涜寮傛璇锋眰锛屽湪enqueue鏂规硶涓紶鍏ヤ竴涓洖璋僀allBack锛岄噸鍐欓噷闈㈢殑onResponse鍜?br>onFailure鏂规硶锛屼篃灏辨槸璇锋眰鎴愬姛鍜屽け璐ョ殑鍥炶皟鏂规硶銆傚綋鎴愬姛鏃讹紝瀹冧細杩斿洖Response锛岄噷杈瑰皝瑁呬簡璇锋眰缁撴灉鐨勬墍鏈変俊鎭紝鍖呮嫭鎶ュご锛岃繑鍥炵爜锛岃繕鏈変富浣撶瓑銆傛瘮濡傝皟鐢ㄥ畠鐨刡ody()鏂规硶灏卞彲鑾峰緱Book瀵硅薄锛屼篃灏辨槸鎴戜滑闇€瑕佺殑鏁版嵁銆傝繖閲屾垜浠氨鎶婅繑鍥炵殑Book锛屾樉绀哄睆骞曚笂銆傚涓嬪浘锛?/p>


Book涓殑鏁版嵁

濂戒簡锛屽埌杩欓噷鎴戜滑灏卞熀鏈簡瑙d簡Retrofit鐨勬暣涓伐浣滄祦绋嬨€?/p>

3.RxJava

鎴戜滑杩欑瘒鏂囩珷涓昏浠嬬粛鎼缓鏁翠綋缃戠粶璇锋眰妗嗘灦锛屾墍浠ュ叧浜嶳xJava鐨勫熀纭€鐭ヨ瘑锛屾垜杩欏氨涓嶅啀璇︾粏浠嬬粛浜嗭紝缃戜笂涔熸湁寰堝鏂囩珷锛屽RxJava杩樹笉鏄緢浜嗚В鐨勫悓瀛︼紝鎺ㄨ崘浣犵湅涓€涓嬫姏鐗╃嚎鐨勮繖绡囨枃绔?a target="_blank" href="http://gank.io/post/560e15be2dca930e00da1083">缁?Android 寮€鍙戣€呯殑 RxJava 璇﹁В

涓嬮潰鎴戜滑鏉ョ湅涓€涓婻xJava鍜宺etrofit鐨勭粨鍚堜娇鐢紝涓轰簡浣縍xjava涓巖etrofit缁撳悎锛屾垜浠渶瑕佸湪Retrofit瀵硅薄寤虹珛鐨勬椂鍊欐坊鍔犱竴鍙ヤ唬鐮?code>addCallAdapterFactory(RxJavaCallAdapterFactory.create())锛屽綋鐒朵綘杩橀渶瑕佸湪build.gradle鏂囦欢涓坊鍔犲涓嬩緷璧栵細

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
瀹屾暣鐨勪唬鐮佸涓嬶細
public interface RetrofitService {
    @GET("book/search")
    Observable<Book> getSearchBook(@Query("q") String name,
                                    @Query("tag") String tag, @Query("start") int start,
                                    @Query("count") int count);
聽鐒跺悗鎴戜滑杩橀渶瑕佷慨鏀筊etrofitService 涓殑浠g爜锛?/div>
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.douban.com/v2/")
        .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//鏀寔RxJava
        .build();
鍙互鐪嬪埌锛屽湪鍘熸潵鐨凴etrofitService 涓垜浠妸getSearchBook鏂规硶杩斿洖鐨勭被鍨婥all鏀逛负浜哋bservable锛屼篃灏辨槸琚瀵熻€呫€傚叾浠栭兘娌″彉銆傜劧鍚庡氨鏄垱寤篟etrofitService 瀹炰綋绫伙細
RetrofitService service = retrofit.create(RetrofitService.class);

鍜屼笂闈竴鏍凤紝鍒涘缓瀹孯etrofitService 锛屽氨鍙互璋冪敤閲岄潰鐨勬柟娉曚簡锛?/p>

Observable<Book> observable =  service.getSearchBook("閲戠摱姊?, null, 0, 1);

鍏跺疄杩欎竴姝ワ紝灏辨槸鍒涘缓浜嗕竴涓猺xjava涓璷bservable锛屽嵆琚瀵熻€?鏈変簡琚瀵熻€咃紝灏遍渶瑕佷竴涓瀵熻€咃紝涓旇闃呭畠锛?/p>

observable.subscribeOn(Schedulers.io())//璇锋眰鏁版嵁鐨勪簨浠跺彂鐢熷湪io绾跨▼
          .observeOn(AndroidSchedulers.mainThread())//璇锋眰瀹屾垚鍚庡湪涓荤嚎绋嬫洿鏄綰I
          .subscribe(new Observer<Book>() {//璁㈤槄
              @Override
              public void onCompleted() {
                  //鎵€鏈変簨浠堕兘瀹屾垚锛屽彲浠ュ仛浜涙搷浣溿€傘€傘€?
              }
              @Override
              public void onError(Throwable e) {
                  e.printStackTrace(); //璇锋眰杩囩▼涓彂鐢熼敊璇?
              }
              @Override
              public void onNext(Book book) {//杩欓噷鐨刡ook灏辨槸鎴戜滑璇锋眰鎺ュ彛杩斿洖鐨勫疄浣撶被    
              }
           }
聽鍦ㄤ笂闈腑鎴戜滑鍙互鐪嬪埌锛屼簨浠剁殑娑堣垂鍦ˋndroid涓荤嚎绋嬶紝鎵€浠ユ垜浠繕瑕佸湪build.gradle涓坊鍔犲涓嬩緷璧栵細

compile 'io.reactivex:rxandroid:1.2.0'

杩欐牱鎴戜滑灏卞紩鍏ヤ簡RxAndroid锛孯xAndroid鍏跺疄灏辨槸瀵筊xJava鐨勬墿灞曘€傛瘮濡備笂闈㈣繖涓狝ndroid涓荤嚎绋嬪湪RxJava涓氨娌℃湁锛屽洜姝よ浣跨敤鐨勮瘽灏卞繀椤诲緱寮曠敤RxAndroid銆?/p>

4.瀹炶返

鎺ヤ笅鏉ユ垜浠氨鐪嬬湅锛屽湪涓€涓」鐩腑涓婇潰涓夎€呮槸濡備綍閰嶅悎鐨勩€傛垜浠墦寮€Android Studio锛屾柊寤轰竴涓」鐩彇鍚嶄负MVPDemo銆傝繖涓猟emo鐨勫姛鑳戒篃寰堢畝鍗曪紝灏辨槸鐐瑰嚮鎸夐挳璋冪敤涓婇潰鐨勯偅涓祴璇曟帴鍙o紝灏嗚姹備笅鏉ヤ功鐨勪俊鎭樉绀哄湪灞忓箷涓娿€傞鍏堟垜浠潵鐪嬩竴涓嬭繖涓伐绋嬬殑鐩綍缁撴瀯锛?/p>


宸ョ▼鐩綍


鎴戜滑鍙互鐪嬪埌锛屽湪椤圭洰鐨勫寘鍚嶄笅锛屾垜浠缓浜嗕笁涓富瑕佺殑鏂囦欢澶癸細app銆乻ervice銆乽i銆傚綋鐒舵牴鎹」鐩殑闇€瑕佷綘涔熷彲浠ユ坊鍔犳洿澶氬叾浠栫殑鏂囦欢澶癸紝姣斿涓€浜涘伐鍏风被绛夈€傚叾涓璦pp鏂囦欢澶逛腑鍙互寤轰竴涓狝pplication绫伙紝鐢ㄤ簬璁剧疆搴旂敤鍏ㄥ眬鐨勪竴浜涘睘鎬э紝杩欓噷涓轰簡浣块」鐩洿鍔犵畝鍗曞氨娌℃湁娣诲姞锛涚劧鍚庯紝鎴戜滑鍐嶆潵鐪嬬湅ui鏂囦欢澶逛笅锛岃繖涓枃浠跺す涓嬩富瑕佹斁涓€浜涘叧浜庣晫闈㈢殑涓滆タ銆傚湪閲岄潰鎴戜滑鍙堝缓浜嗕笁涓枃浠跺す锛歛ctivity銆乤dapter銆乫ragment锛屾垜鎯崇湅鍚嶅瓧浣犲氨娓呮閲岄潰瑕佹斁浠€涔堜簡銆傛渶鍚庢垜浠湪閲嶇偣鐪嬬湅service鏂囦欢澶逛腑鐨勪笢瑗裤€傞鍏堟垜浠潵鐪嬬湅閲岄潰閲嶈鐨勪袱涓被锛歊etrofitHelper鍜孯etrofitService銆俁etrofitHelper涓昏鐢ㄤ簬Retrofit鐨勫垵濮嬪寲锛?/p>

public class RetrofitHelper {

    private Context mCntext;

    OkHttpClient client = new OkHttpClient();
    GsonConverterFactory factory = GsonConverterFactory.create(new GsonBuilder().create());
    private static RetrofitHelper instance = null;
    private Retrofit mRetrofit = null;
    public static RetrofitHelper getInstance(Context context){
        if (instance == null){
            instance = new RetrofitHelper(context);
        }
        return instance;
    }
    private RetrofitHelper(Context mContext){
        mCntext = mContext;
        init();
    }

    private void init() {
        resetApp();
    }

    private void resetApp() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl("https://api.douban.com/v2/")
                .client(client)
                .addConverterFactory(factory)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }
    public RetrofitService getServer(){
        return mRetrofit.create(RetrofitService.class);
    }
}
聽浠g爜骞朵笉澶嶆潅锛屽叾涓璻esetApp鏂规硶锛屽氨鏄墠闈粙缁嶇殑Retrofit鐨勫垱寤猴紝getServer鏂规硶灏辨槸涓轰簡鑾峰彇RetrofitService鎺ュ彛绫荤殑瀹炰緥鍖栥€傜劧鍚庡畾涔変簡涓€涓潤鎬佹柟娉昰etInstance鐢ㄤ簬鑾峰彇鑷韩RetrofitHelper鐨勫疄渚嬪寲锛屽苟涓斿彧浼氬疄渚嬪寲涓€娆°€?/div>

鎺ヤ笅鏉ワ紝鐪嬩竴涓婻etrofitService锛屽叾涓唬鐮佽繕鏄笂闈竴鏍凤細

public interface RetrofitService {
    @GET("book/search")
    Observable<Book> getSearchBooks(@Query("q") String name,
                                    @Query("tag") String tag, @Query("start") int start,
                                    @Query("count") int count);
}

鐒跺悗鎴戜滑渚濇鏉ョ湅涓€涓媠ervice鏂囦欢澶逛笅鐨勫洓涓枃浠跺す锛歟ntity銆乵anager銆乸resenter鍜寁iew銆傚叾涓璭ntity涓嬫斁鎴戜滑璇锋眰鐨勫疄浣撶被锛岃繖閲屽氨鏄疊ook銆傛帴涓嬫潵鎴戜滑鏉ョ湅涓€涓媘anager涓璂ataManager銆傝繖涓被鍏跺疄灏辨槸涓轰簡璁╀綘鏇存柟渚跨殑璋冪敤RetrofitService 涓畾涔夌殑鏂规硶锛?/div>
public class DataManager {
    private RetrofitService mRetrofitService;
    public DataManager(Context context){
        this.mRetrofitService = RetrofitHelper.getInstance(context).getServer();
    }
    public  Observable<Book> getSearchBooks(String name,String tag,int start,int count){
        return mRetrofitService.getSearchBooks(name,tag,start,count);
    }
}
聽鍙互鐪嬪埌锛屽湪瀹冪殑鏋勯€犳柟娉曚腑锛屾垜浠緱鍒颁簡RetrofitService 鐨勫疄渚嬪寲锛岀劧鍚庡畾涔変簡涓€涓拰RetrofitService 涓悓鍚嶇殑鏂规硶锛岄噷闈㈠叾瀹炲氨鏄皟鐢≧etrofitService 涓殑杩欎釜鏂规硶銆傝繖鏍凤紝鎶奟etrofitService 涓畾涔夌殑鏂规硶閮藉皝瑁呭埌DataManager 涓紝浠ュ悗鏃犺鍦ㄥ摢涓璋冪敤鏂规硶鏃剁洿鎺ュ湪DataManager 涓皟鐢ㄥ氨鍙互浜嗭紝鑰屼笉鏄噸澶嶅缓绔婻etrofitService 鐨勫疄渚嬪寲锛屽啀璋冪敤鍏朵腑鐨勬柟娉曘€?

濂戒簡锛屾垜浠啀鏉ョ湅涓€涓媝resenter鍜寁iew锛屾垜浠湪鍓嶉潰璇磋繃锛宲resenter涓昏鐢ㄤ簬缃戠粶鐨勮姹備互鍙婃暟鎹殑鑾峰彇锛寁iew灏辨槸灏唒resenter鑾峰彇鍒扮殑鏁版嵁杩涜灞曠ず銆傞鍏堟垜浠厛鏉ョ湅view锛屾垜浠湅鍒版垜浠缓浜嗕袱涓帴鍙g被View鍜孊ookView,鍏朵腑View鏄┖鐨勶紝涓昏鐢ㄤ簬鍜孉ndroid涓殑View鍖哄埆寮€鏉ワ細

public interface View {
}

鐒跺悗璁〣ookView缁ф壙鑷垜浠嚜宸卞畾涔夌殑View 锛?/p>

public interface BookView extends View {
    void onSuccess(Book mBook);
    void onError(String result);
}

鍙互鐪嬪埌鍦ㄩ噷闈㈠畾涔変袱涓柟娉曪紝涓€涓猳nSuccess锛屽鏋減resenter璇锋眰鎴愬姛锛屽皢鍚戣鏂规硶浼犲叆璇锋眰涓嬫潵鐨勫疄浣撶被锛屼篃灏辨槸Book锛寁iew鎷垮埌杩欎釜鏁版嵁瀹炰綋绫诲悗锛屽氨鍙互杩涜鍏充簬杩欎釜鏁版嵁鐨勫睍绀烘垨鍏朵粬鐨勪竴浜涙搷浣溿€傚鏋滆姹傚け璐ワ紝灏变細鍚戣繖涓獀iew浼犲叆澶辫触淇℃伅锛屼綘鍙互寮逛釜Toast鏉ユ彁绀鸿姹傚け璐ャ€傞€氬父杩欎袱涓柟娉曟瘮杈冨父鐢紝褰撶劧浣犲彲浠ユ牴鎹」鐩渶瑕佹潵瀹氫箟涓€浜涘叾浠栫殑鏂规硶銆傛帴涓嬫潵鎴戜滑鐪嬬湅presenter鏄浣曡繘琛岀綉缁滆姹傜殑 銆傛垜浠篃瀹氫箟浜嗕竴涓熀纭€Presenter锛?/p>

public interface Presenter {
    void onCreate();

    void onStart();//鏆傛椂娌$敤鍒?

    void onStop();

    void pause();//鏆傛椂娌$敤鍒?

    void attachView(View view);

    void attachIncomingIntent(Intent intent);//鏆傛椂娌$敤鍒?
}
聽閲岄潰鎴戜滑鍙互鐪嬪埌锛屽畾涔変簡涓€浜涙柟娉曪紝鍓嶉潰鍑犱釜onCreate銆乷nStart绛夋柟娉曞搴旂潃Activity涓敓鍛藉懆鏈熺殑鏂规硶锛屽綋鐒舵病蹇呰鍐欎笂Activity鐢熷懡鍛ㄦ湡涓墍鏈夊洖璋冩柟娉曪紝閫氬父涔熷氨鐢ㄥ埌浜唎nCreate鍜宱nStop锛岄櫎闈為渶姹傚緢澶嶆潅锛屽湪Activity涓嶅悓鐢熷懡鍛ㄦ湡璇锋眰鐨勬儏鍐典笉鍚屻€傛帴鐫€鎴戜滑瀹氫箟浜嗕竴涓猘ttachView鏂规硶锛岀敤浜庣粦瀹氭垜浠畾涔夌殑View銆備篃灏辨槸锛屼綘鎯虫妸璇锋眰涓嬫潵鐨勬暟鎹疄浣撶被缁欏摢涓猇iew灏变紶鍏ュ摢涓猇iew銆備笅闈㈣繖涓猘ttachIncomingIntent鏆備笖娌$敤鍒帮紝灏变笉璇翠簡銆傚ソ浜嗭紝鎴戜滑鏉ョ湅涓€涓婤ookPresenter鍏蜂綋鏄€庝箞瀹炵幇鐨勶細
public class BookPresenter implements Presenter {
    private DataManager manager;
    private CompositeSubscription mCompositeSubscription;
    private Context mContext;
    private BookView mBookView;
    private Book mBook;
    public BookPresenter (Context mContext){
        this.mContext = mContext;
    }
    @Override
    public void onCreate() {
        manager = new DataManager(mContext);
        mCompositeSubscription = new CompositeSubscription();
    }

    @Override
    public void onStart() {

    }

    @Override
    public void onStop() {
        if (mCompositeSubscription.hasSubscriptions()){
            mCompositeSubscription.unsubscribe();
        }
    }

    @Override
    public void pause() {

    }

    @Override
    public void attachView(View view) {
        mBookView = (BookView)view;
    }

    @Override
    public void attachIncomingIntent(Intent intent) {
    }
    public void getSearchBooks(String name,String tag,int start,int count){
        mCompositeSubscription.add(manager.getSearchBooks(name,tag,start,count)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Book>() {
                    @Override
                    public void onCompleted() {
                        if (mBook != null){
                            mBookView.onSuccess(mBook);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        mBookView.onError("璇锋眰澶辫触锛侊紒");
                    }

                    @Override
                    public void onNext(Book book) {
                        mBook = book;
                    }
                })
        );
    }
}
聽BookPresenter瀹炵幇浜嗘垜浠畾涔夌殑鍩虹Presenter锛屽湪onCreate涓垜浠垱寤轰簡DataManager鐨勫疄浣撶被锛屼究浜庤皟鐢≧etrofitService涓殑鏂规硶锛岃繕鏂板缓浜嗕竴涓狢ompositeSubscription瀵硅薄锛孋ompositeSubscription鏄敤鏉ュ瓨鏀綬xJava涓殑璁㈤槄鍏崇郴鐨勩€傛敞鎰忚姹傚畬鏁版嵁瑕佸強鏃舵竻鎺夎繖涓闃呭叧绯伙紝涓嶇劧浼氬彂鐢熷唴瀛樻硠婕忋€傚彲鍦╫nStop涓€氳繃璋冪敤CompositeSubscription鐨剈nsubscribe鏂规硶鏉ュ彇娑堣繖涓闃呭叧绯伙紝涓嶈繃涓€鏃﹁皟鐢ㄨ繖涓柟娉曪紝閭d箞杩欎釜CompositeSubscription涔熷氨鏃犳硶鍐嶇敤浜嗭紝瑕佹兂鍐嶇敤鍙兘閲嶆柊new涓€涓€傜劧鍚庢垜浠彲浠ョ湅鍒板湪attachView涓紝鎴戜滑鎶夿ookView浼犺繘鍘汇€備篃灏辨槸璇存垜浠鎶婅姹備笅鏉ョ殑瀹炰綋绫讳氦缁橞ookView鏉ュ鐞嗐€傛帴涓嬫潵鎴戜滑瀹氫箟浜嗕竴涓柟娉昰etSearchBooks锛屽悕瀛楀拰鍏ュ弬閮藉拰璇锋眰鎺ュ彛RetrofitService涓殑鏂规硶鐩稿悓銆傝繖閲岀殑杩欎釜鏂规硶涔熷氨鏄姹傜殑鍏蜂綋瀹炵幇杩囩▼銆傚叾瀹炰篃寰堢畝鍗曪紝灏辨槸鍚慍ompositeSubscription娣诲姞涓€涓闃呭叧绯汇€備笂闈㈡垜浠凡缁忚杩噈anager.getSearchBooks灏辨槸璋冪敤RetrofitService鐨刧etSearchBooks鏂规硶锛岃€岃繖涓柟娉曡繑鍥炵殑鏄竴涓硾鍨嬩负Book鐨凮bservable锛屽嵆琚瀵熻€咃紝鐒跺悗閫氳繃subscribeOn(Schedulers.io())鏉ュ畾涔夎姹備簨浠跺彂鐢熷湪io绾跨▼锛岀劧鍚庨€氳繃observeOn(AndroidSchedulers.mainThread())鏉ュ畾涔変簨浠跺湪涓荤嚎绋嬫秷璐癸紝鍗冲湪涓荤嚎绋嬭繘琛屾暟鎹殑澶勭悊锛屾渶鍚庨€氳繃subscribe浣胯瀵熻€呰闃呭畠銆傚湪瑙傚療鑰呬腑鏈変笁涓柟娉曪細onNext銆乷nCompleted銆乷nError銆傚綋璇锋眰鎴愬姛璇濓紝灏变細璋冪敤onNext锛屽苟浼犲叆璇锋眰杩斿洖鐨凚ook瀹炰綋绫伙紝鎴戜滑鍦╫nNext涓紝鎶婅姹備笅鏉ョ殑Book瀹炰綋绫诲瓨鍒板唴瀛樹腑锛屽綋璇锋眰缁撴潫鍚庝細璋冪敤onCompleted锛屾垜浠妸璇锋眰涓嬫潵鐨凚ook瀹炰綋绫讳氦缁橞ookView澶勭悊灏卞彲浠ヤ簡锛屽鏋滆姹傚け璐ワ紝閭d箞涓嶄細璋冪敤onCompleted鑰岃皟鐢╫nError锛岃繖鏍锋垜浠彲浠ュ悜BookView浼犻€掗敊璇秷鎭€?

濂戒簡锛岃繖鏍锋垜浠垜浠氨鍙互璋冪敤杩欎釜鎺ュ彛鏂规硶鏉ヨ繘琛岀綉缁滅殑璇锋眰浜嗭紝鎴戜滑鍏堝啓涓€涓嬮〉闈㈢殑甯冨眬锛?/p>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    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:orientation="vertical"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <Button
        android:id="@+id/button"
        android:onClick="getFollowers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="璇锋眰"/>
</LinearLayout>
鐣岄潰寰堢畝鍗曪紝涓€鍏变袱涓帶浠讹紝涓€涓狟utton锛岀偣鍑绘椂杩涜缃戠粶璇锋眰锛屼竴涓猅extView锛岀敤浜庢樉绀鸿姹備笅鏉ョ殑鏁版嵁銆傜劧鍚庢垜涔堢湅涓€涓婣ctivity涓唬鐮侊細
public class MainActivity extends AppCompatActivity {

    private TextView text;
    private Button button;
    private BookPresenter mBookPresenter = new BookPresenter(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView)findViewById(R.id.text);
        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBookPresenter.getSearchBooks("閲戠摱姊?, null, 0, 1);
            }
        });
        mBookPresenter.onCreate();
        mBookPresenter.attachView(mBookView);
    }

    private BookView mBookView = new BookView() {
        @Override
        public void onSuccess(Book mBook) {
            text.setText(mBook.toString());
        }

        @Override
        public void onError(String result) {
            Toast.makeText(MainActivity.this,result, Toast.LENGTH_SHORT).show();
        }
    };
    @Override
    protected void onDestroy(){
        super.onDestroy();
        mBookPresenter.onStop();
    }
}
閫昏緫骞朵笉澶嶆潅锛屾垜浠厛鍒涘缓浜嗕竴涓狟ookPresenter 瀵硅薄锛岀劧鍚庤皟鐢ㄥ畠鐨刼nCreate鏂规硶杩涜鍒濆鍖栵紝鎺ョ潃璋冪敤attachView鏉ョ粦瀹欱ookView銆侭ookView鐨勫疄鐜颁篃寰堢畝鍗曪紝鍦╫nSuccess鏂规硶涓皢Book 涓唴瀹规樉绀哄湪TextView涓婏紝鍦╫nError涓脊鍑轰竴涓猅oast鎻愮ず銆傜劧鍚庣偣鍑绘寜閽殑鏃跺€欏氨璋冪敤BookPresenter涓璯etSearchBooks鏂规硶锛屽悓鏃朵紶鍏ュ繀瑕佺殑鍏ュ弬銆傝繖鏍风綉缁滆姹傚氨寮€濮嬩簡锛屽鏋滆姹傛垚鍔熷氨浼氬洖璋傿ookView 涓殑onSuccess鏂规硶锛屽け璐ュ氨鍥炶皟onError鏂规硶銆傚綋娲诲姩閿€姣佹椂璁板緱璋冪敤BookPresenter鐨刼nStop鏂规硶鏉ラ噴鏀捐闃呭叧绯伙紝闃叉鍐呭瓨娉勬紡銆?

鏈€鍚庡埆蹇樹簡鍦ˋndroidManifest涓坊鍔犵綉缁滄潈闄愶細

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

濂戒簡锛屾垜浠繍琛屼竴涓嬬湅涓€涓嬫晥鏋滐細


婕旂ず

浠g爜宸蹭笂浼爂ithub锛?a target="_blank" href="https://github.com/Lloyd0577/MVPDemo">MVPDemo

相关解决方案

最新解决方案