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(); } }