http://www.jianshu.com/p/7b839b7c5884 推薦 ,照着這個敲完 , 測試成功 , 推薦你們都去看一下 。 json
下面貼一下我照着這個敲完的代碼:api
Book實體類 - 用於封裝網絡請求返回的數據; 這個藉助GsonFormat 插件,注意若實體類有實體,必定要手動實現toString();網絡
public interface RetrofitService { /** //拼接一個URL而後進行網絡請求 //這裏咱們拼接的URL就是 完整URL:https://api.douban.com/v2/book/search?q=xxx&tag=&start=0&count=1; //每一個URL前面都是以http://www.jianshu.com/開頭,咱們把這個不變的部分,也叫作baseUrl提出來,放到另外一個地方,在下面咱們會提到 */ //將返回值call改成observable @GET("book/search") Observable<Book> getSearchBook(@Query("q") String name, @Query("tag") String tag, @Query("start") int start, @Query("count") int count ); /** * 在每一個入參前還多了一個註解。好比第一個入參@Query("q") String name,Query表示把你傳入的字段拼接起來 * 這個url須要幾個入參你就在這個方法中定義幾個入參,每一個入參前都要加上Query註解 * * @GET("book/search") Call<Book> getSearchBook(@Query("q") String name);//name由調用者傳入 @GET("book/search?q=name") Call<Book> getSearchBook(); ********************************************************** 若是入參比較多,就能夠把它們都放在Map中 @GET("book/search") Call<Book> getSearchBook(@QueryMap Map<String, String> options); *********************************************************** 用於替換url中某個字段 @GET("group/{id}/users") Call<Book> groupList(@Path("id") int groupId); ******************************************************* 指定一個對象做爲HTTP請求體 @POST("users/new") Call<User> createUser(@Body User user); 它會把咱們傳入的User實體類轉換爲用於傳輸的HTTP請求體,進行網絡請求 ********************************************************** 傳送表單數據 @FormUrlEncoded @POST("user/edit") Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last); */ }
/** * Created by lemon on 2017/11/20. * 主要用於Retrofit的初始化: */ 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; //靜態方法getInstance用於獲取自身RetrofitHelper的實例化,而且只會實例化一次。 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方法進行轉換。 // 因爲返回的數據爲json類型,因此在這個方法中傳入Gson轉換工廠 .addConverterFactory(factory) //支持RXJava .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } //建立RetrofitService的實體類 //getServer方法就是爲了獲取RetrofitService接口類的實例化。 public RetrofitService getServer(){ return mRetrofit.create(RetrofitService.class); } }
/** * Created by lemon on 2017/11/20. * 這個是和其餘層直接調用的接口 * 讓你更方便的調用RetrofitService 中定義的方法: */ public class DataManager { private RetrofitService mRetrofitService; // 在它的構造方法中,咱們獲得了RetrofitService 的實例化 // 這樣,把RetrofitService 中定義的方法都封裝到DataManager 中, // 之後不管在哪一個要調用方法時直接在DataManager 中調用就能夠了, // 而不是重複創建RetrofitService 的實例化,再調用其中的方法。 public DataManager(Context context){ this.mRetrofitService = RetrofitHelper.getInstance(context).getServer(); } public Observable<Book> getSearchBooks(String name, String tag, int start, int count){ return mRetrofitService.getSearchBook(name,tag,start,count); } }
/** * Created by lemon on 2017/11/20. * presenter主要用於網絡的請求以及數據的獲取,view就是將presenter獲取到的數據進行展現。 */ public interface Presenter { void onCreate(); void onStart();//暫時沒用到 void onStop(); void pause();//暫時沒用到 /* 用於綁定咱們定義的View.也就是,你想把請求下來的數據實體類給哪一個View就傳入哪一個View */ void attachView(BookView view); void attachIncomingIntent(Intent intent);//暫時沒用到 }
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); /** * CompositeSubscription是用來存放RxJava中的訂閱關係的。 * 注意請求完數據要及時清掉這個訂閱關係,否則會發生內存泄漏。 * 可在onStop中經過調用CompositeSubscription的unsubscribe方法來取消這個訂閱關係, * 不過一旦調用這個方法,那麼這個CompositeSubscription也就沒法再用了,要想再用只能從新new一個。 */ mCompositeSubscription = new CompositeSubscription(); } @Override public void onStart() { } @Override public void onStop() { if (mCompositeSubscription.hasSubscriptions()){ mCompositeSubscription.unsubscribe(); } } @Override public void pause() { } //想把請求下來的數據實體類給哪一個View就傳入哪一個View //在attachView中,咱們把BookView傳進去。也就是說咱們要把請求下來的實體類交給BookView來處理。 @Override public void attachView(BookView view) { mBookView = view; } @Override public void attachIncomingIntent(Intent intent) { } /** * 名字和入參都和請求接口RetrofitService中的方法相同。這個方法也就是請求的具體實現過程。 */ public void getSearchBook(String name,String tag,int start,int count){ mCompositeSubscription.add(manager.getSearchBooks(name, tag, start, count) .subscribeOn(Schedulers.io()) //請求數據的事件發生在IO線程 .observeOn(AndroidSchedulers.mainThread()) //請求完成後在主線程更新UI .subscribe(new Observer<Book>() { @Override public void onCompleted() { //全部的事件都完成,可作這些操做 if(mBook != null){ mBookView.onSuccess(mBook); } } @Override public void onError(Throwable throwable) { //請求過程當中發生錯誤 throwable.printStackTrace(); mBookView.onError("請求失敗!!"); } @Override public void onNext(Book book) { //這裏的BOOK就是咱們請求接口返回的實體類 mBook = book; } }) ); } }
/** * Created by lemon on 2017/11/20. * View是空的,主要用於和Android中的View區別開來 */ public interface View { }
public interface BookView extends View { /** * 若是presenter請求成功,將向該方法傳入請求下來的實體類, * 也就是Book,view拿到這個數據實體類後,就能夠進行關於這個數據的展現或其餘的一些操做 * @param mBook */ void onSuccess(Book mBook); /** * 若是請求失敗,就會向這個view傳入失敗信息,你能夠彈個Toast來提示請求失敗 * @param result */ void onError(String result); }
public class BookActivity extends AppCompatActivity { private TextView text ; private Button btn ; private BookPresenter mBookPresenter = new BookPresenter(this); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_message); text = (TextView) findViewById(R.id.text); btn = (Button) findViewById(R.id.button); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mBookPresenter.getSearchBook("xxx",null,0,1); } }); mBookPresenter.onCreate(); mBookPresenter.attachView(mBookView); } private BookView mBookView = new BookView() { @Override public void onSuccess(Book mBook) { Log.e("log","mbook"+mBook.toString()); text.setText(mBook.toString()); } @Override public void onError(String result) { Toast.makeText(BookActivity.this,result, Toast.LENGTH_SHORT).show(); } }; @Override protected void onDestroy() { super.onDestroy(); mBookPresenter.onStop(); } }