標籤:
轉載請註明出處:http://blog.csdn.net/finddreams/article/details/50849385#0-qzone-1-61707-d020d2d2a4e8d1a374a433f596ad1440
一起分享,一起進步。finddreams:http://blog.csdn.net/finddreams/article/details/50849385
眾所周知,手機APP的核心就在於調用後台介面,展示相關資訊,方便我們在手機上就能和外界互動。所以APP中網路架構的搭建一直是我們開發人員所關心的問題,在Android中關於如何搭建網路架構分為兩種:一種是不想重複造輪子使用第三方開源的網路架構;第二種就是喜歡造輪子的封裝自己的網路架構。
自己封裝實現網路架構這種行為固然不錯,但是這需要自身具備比較高的能力,而很多時候我們沒有那樣的能力把它封裝的足夠好。這時我們使用開源的網路架構也未嘗不是一件好事,github上面知名的網路架構已經經過了很多app的驗證,在一定意義上是非常符合我們在實際的項目開發所需要的。
Android開發中幾個知名的開源的網路架構有android-async-http,Volley,OkHttp等,國人 開發的xUtils快速開發架構也比較流行。android-async-http是個很老牌的網路架構,非常的經典。Volley官方推薦的,自不必說。OkHttp可以說是後起之秀,現在非常流行,Android系統底層api都有用到,所以是非常niubility.
我們很多開發人員大都在小型公司,不瞭解大公司是怎麼做Android網路架構的,也想知道那些使用者量過千萬的APP到底用了些什麼技術,下面有兩張圖片,讓我們一起來瞭解一下Android版的美團和Uber到底用了些什麼技術。
美團 Uber
看完你會發現其實這些使用者量過億的APP也使用了很多的開源架構,而且這些開源架構中大多數其實都是我們平常在開發中所常用到的,並不陌生。可能大多數人對Retrofit,Rxjava這些還不太熟悉,那話不多說,今天我們就來講講怎麼用Retrofit2.0+RxJava+Dragger2來實現Android網路構架搭建,給大家提供一種思路,供大家參考參考。
Retrofit2.0 GitHub:https://github.com/square/retrofit
Square開發的型別安全的REST安卓用戶端請求庫,網路請求預設使用的是OkHttp,具體介紹請看相關教程。
RxJava +RxAndroid GitHub地址: https://github.com/ReactiveX/RxJava
RxJava是一種響應式編程架構,採用觀察者設計模式。最核心的是Observables(被觀察者,事件來源)和Subscribers(觀察者)這兩個東西,RxAndroid是Rxjava在Android上的實現。
Dragger2
是一種依賴注入架構,可以大大節省我們的代碼量,便於維護。
在這裡我就不費過多筆墨來介紹著三個東西了,今天的主題是提供一種如何搭建一個不一樣的網路架構的思路。如果讀者對這三個架構不是很瞭解的話,可以自行的Google腦補一下。
首先,就是開始把這些架構引入到咱們的項目中來作為依賴庫,在app/build.gradle檔案中添加
apply plugin: ‘com.android.application‘apply plugin: ‘com.neenbedankt.android-apt‘android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.finddreams.retrofit" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘ } }}dependencies { compile fileTree(include: [‘*.jar‘], dir: ‘libs‘) testCompile ‘junit:junit:4.12‘ compile ‘com.android.support:appcompat-v7:23.1.1‘ //retrofit compile ‘com.squareup.retrofit2:retrofit:2.0.0-beta4‘ //gson解析 compile ‘com.squareup.retrofit2:converter-gson:2.0.0-beta4‘ //rxjava compile ‘io.reactivex:rxandroid:1.1.0‘ compile ‘com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4‘ //dragger2 provided ‘org.glassfish:javax.annotation:10.0-b28‘ apt ‘com.google.dagger:dagger-compiler:2.0.2‘ compile ‘com.google.dagger:dagger:2.0.2‘}
因為Dragger2是基於註解的,它會預先產生一些類檔案,所以需要在整個項目的/build.gradle檔案中加上apt工具:
buildscript { repositories { jcenter() } dependencies { classpath ‘com.android.tools.build:gradle:2.0.0-beta6‘ classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8‘ // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}allprojects { repositories { jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}
接著開始寫一個提供Retrofit的單例類:
/** * Retrofit的實體類 */public class RestApiAdapter { private static Retrofit retrofit = null; public static Retrofit getInstance() { if (retrofit == null) { GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(); OkHttpClient okHttpClient = new OkHttpClient(); OkHttpClient.Builder builder = okHttpClient.newBuilder(); builder.retryOnConnectionFailure(true); retrofit = new Retrofit.Builder().client(okHttpClient) .baseUrl(ConstantApi.BaiduUrl) .addConverterFactory(gsonConverterFactory) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } return retrofit; }}
addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 這個方法就是RxJava和Retrofit結合的關鍵。
接著我們為Retrofit 提供一個service介面,聲明api介面地址和所需要的參數,這裡我們使用百度API提供的天氣介面,實現根據城市名稱查詢天氣的功能,介面地址:http://apistore.baidu.com/apiworks/servicedetail/112.html 代碼如下:
/** * 天氣介面Api */public interface WeatherApiService { /** * 查詢天氣 */ @GET("apistore/weatherservice/cityname") Observable<WeatherResultBean> queryWeather(@Header("apikey") String apikey, @Query("cityname") String cityname);}
返回一個Observable被觀察者/事件來源的意思是交給RxJava來處理。
然後我們寫一個BaseSubsribe觀察者來管理網路請求開始結束,成功與失敗:
/** * 觀察者 * * @author finddreams * @address http://blog.csdn.net/finddreams */public abstract class BaseSubsribe<T> extends Subscriber<T> { private static final String TAG = "BaseSubsribe"; @Override public void onStart() { super.onStart(); Log.i(TAG, "onStart"); } @Override public void onNext(T t) { Log.i(TAG, "response" + t.toString()); onSuccess(t); } @Override public void onCompleted() { Log.i(TAG, "onCompleted"); } public abstract void onSuccess(T result); @Override public void onError(Throwable e) { e.printStackTrace(); Log.i(TAG, "onError" + e.getMessage()); }}
接著我們寫一個WeatherInteractor介面串連service類:
/** * 擷取天氣資訊介面 * * @author finddreams * @address http://blog.csdn.net/finddreams */public interface WeatherInteractor { Subscription queryWeather(String apikey, String cityname, BaseSubsribe<WeatherResultBean> subsribe);}
然後是這個介面的實作類別:
/** * 擷取天氣資訊實作類別 */public class WeatherInteractorImpl implements WeatherInteractor { private final WeatherApiService api; @Inject public WeatherInteractorImpl(WeatherApiService myApi) { this.api = myApi; } @Override public Subscription queryWeather(String apikey, String cityname, BaseSubsribe<WeatherResultBean> subsribe) { Observable<WeatherResultBean> observable = api.queryWeather(apikey, cityname); Subscription subscribe = observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subsribe); return subscribe; }}
接下來是如何使用Dragger2的時候,知道Dragger2的都知道有幾個概念,一個是Module:主要提供依賴對象比如context, rest api …; 一個是@inject:註解,用在需要依賴對象的地方;另一個是Componet:用來串連Module和@inject
首先定義一個Module類,提供需要注入依賴的對象:
/** * Module類 * 提供需要注入的類 * * @author finddreams * @address http://blog.csdn.net/finddreams */@Modulepublic class InteractorModule { @Provides public Retrofit provideRestAdapter() { return RestApiAdapter.getInstance(); } @Provides public WeatherApiService provideHomeApi(Retrofit restAdapter) { return restAdapter.create(WeatherApiService.class); } @Provides public WeatherInteractor provideHomeInteractor(WeatherApiService myApi) { return new WeatherInteractorImpl(myApi); }}
接著是寫一個Componet類:
/** * 聲明AppComponent組件 * * @author finddreams * @address http://blog.csdn.net/finddreams */@Singleton@Component( modules = { InteractorModule.class, })public interface AppComponent { void inject(App app); WeatherInteractor getWeatherInteractor();}
然後我們在Application中初始化這個AppComponent:
/** * Application類 * * @author finddreams * @address http://blog.csdn.net/finddreams */public class App extends Application { private AppComponent component; @Override public void onCreate() { super.onCreate(); setDraggerConfig(); } public AppComponent component() { return component; } public static App get(Context context) { return (App) context.getApplicationContext(); } /** * 初始化Dragger,DaggerAppComponent是自動產生,需要Rebuild */ private void setDraggerConfig() { component = DaggerAppComponent.builder().interactorModule(new InteractorModule()) .build(); component.inject(this); }}
這裡需要注意的是,由於Dagger2是先行編譯產生一個類,所以我們需要Rebuild項目,才會產生DaggerAppComponent這個類。如果開發中出現
import com.finddreams.retrofit.api.config.DaggerAppComponent;找不到這個類的錯誤
這時就需要重新的Rebuild項目
這是Rebuild項目之後產生的class檔案,
最後我們就可以在Activity中開始使用了:
/** * 首頁 * * @author finddreams * @address http://blog.csdn.net/finddreams */public class MainActivity extends AppCompatActivity { private AppComponent component; private WeatherInteractor weatherInteractor; private EditText city; private TextView queryresult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); city = (EditText) findViewById(R.id.city); queryresult = (TextView) findViewById(R.id.queryresult); //擷取到AppComponent組件 component = App.get(this).component(); //通過AppComponent拿到WeatherInteractor weatherInteractor = component.getWeatherInteractor(); findViewById(R.id.query).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { queryWeatherData(); } }); } public void queryWeatherData() { String content = city.getText().toString(); //調用查詢天氣介面的方法 Subscription subscription = weatherInteractor.queryWeather(ConstantApi.baiduKey, content, new BaseSubsribe<WeatherResultBean>() { @Override public void onSuccess(WeatherResultBean result) { WeatherResultBean.RetDataEntity retData = result.getRetData(); queryresult.setText(retData.getCity() + ":" + retData.getWeather() + ":" + retData.getDate()); } @Override public void onError(Throwable e) { super.onError(e); queryresult.setText("查詢失敗"); } } ); //取消請求// subscription.unsubscribe(); }}
我們看下項目啟動並執行結果圖:
附上源碼給有需要的朋友參考一下,比較結合源碼才能理解的更透徹,GitHub: https://github.com/finddreams/Retrofit2_Rxjava_Dagger2
基於Retrofit2.0+RxJava+Dragger2實現不一樣的Android網路構架搭建(轉載)