美文网首页
android MVP dagger2 Retrofit

android MVP dagger2 Retrofit

作者: loger | 来源:发表于2017-08-10 00:07 被阅读0次

    前面两片文章中已经完成了Android MVP模式及dagger2的引入, 接下来我们将在前两天的代码的基础上引入Retrofit Rxjava Okhttp实现网络请求; 其中网络请求部分我讲以网络公共api为例子进行网络请求, 如果有开发这发现该地址无法返回数据时,可以联系我进行代码更新。微信号为: lg878398509; 添加时请备注!!!

    1. 在Service包下分别建立api,client, converter包

    • api, 包中存放的是网络请求的 api 请求方法信息
    • client, 中封装了网络请求的框架; 包含Retrofit Okhttp的基础信息
    • converter ,自定义数据返回解析转换工厂类[实现输出原始返回数据的json报文]

    MainApi.java

    public interface MainApi {
        @GET("json/play/list.json?v=3.0.1&os=1&ver=4")
        Observable<ResponseResult> getLiveListResult();
    
    }
    

    ApiEndpoint.java

    public interface ApiEndpoint {
    
        String getEndpoint();
    }
    

    BaseOkHttpClient.java 定义基础OkHttpClient对象信息, 供其他地方继承

    public abstract class BaseOkHttpClient {
    
        private static final long TIMEOUT_CONNECT = 30 * 1000;
    
        public OkHttpClient get() {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
    
            builder.connectTimeout(TIMEOUT_CONNECT, TimeUnit.MILLISECONDS)
                    .addInterceptor(new HttpLoggingInterceptor()
                    .setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE));
    
            builder = customize(builder);
    
            return builder.build();
        }
    
        public abstract OkHttpClient.Builder customize(OkHttpClient.Builder builder);
    
    }
    

    BaseRetrofit.java 基础Retrofit信息类

    public abstract class BaseRetrofit {
    
        public Retrofit get() {
            Retrofit.Builder builder = new Retrofit.Builder();
    
            builder.baseUrl(getApiEndpoint().getEndpoint())
                    .client(getHttpClient())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(ResponseConvertFactory.create());
    
            return builder.build();
        }
    
        public abstract ApiEndpoint getApiEndpoint();
        public abstract OkHttpClient getHttpClient();
    
    }
    

    CacheHttpClient.java 实现缓存功能的OkHttpClient;继承BaseOkHttp

    public class CacheHttpClient extends BaseOkHttpClient {
    
        private static final long CACHE_SIZE = 1024 * 1024 * 50;
    
        @Inject
        Application mContext;
    
        @Inject
        public CacheHttpClient() {
        }
    
        @Override
        public OkHttpClient.Builder customize(OkHttpClient.Builder builder) {
            // set cache dir
            File cacheFile = new File(mContext.getCacheDir(), "appBase");
            Cache cache = new Cache(cacheFile, CACHE_SIZE);
            builder.cache(cache);
    
            builder.addNetworkInterceptor(mCacheControlInterceptor);
            return builder;
        }
    
        private final Interceptor mCacheControlInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
    
                // Add FORCE_CACHE cache control for each request if network is not available.
                if (!NetworkUtil.isNetworkAvailable(mContext)) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
    
                Response originalResponse = chain.proceed(request);
    
                if (NetworkUtil.isNetworkAvailable(mContext)) {
    
                    String cacheControl = request.cacheControl().toString();
    
                    // Add cache control header for response same as request's while network is available.
                    return originalResponse.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .build();
                } else {
                    // Add cache control header for response to FORCE_CACHE while network is not available.
                    return originalResponse.newBuilder()
                            .header("Cache-Control", CacheControl.FORCE_CACHE.toString())
                            .build();
                }
            }
        };
    }
    

    DemoHttpClient.java Demo项目使用的HttpClient; 继承CacheHttpClient; 如果不需要缓存功能则直接继承BaseHttpClient

    public class DemoHttpClient extends CacheHttpClient {
    
        @Inject
        public Application application;
    
        @Inject
        public DemoHttpClient() {
        }
    
        @Override
        public OkHttpClient.Builder customize(OkHttpClient.Builder builder) {
            builder = super.customize(builder);
            return builder;
        }
    }
    

    DemoRetrofit.java Demo项目使用的Retrofit, 继承BaseRetrofit。

    成员变量 “END_POINT” 为后台的BaseURL

    public class DemoRetrofit extends BaseRetrofit {
    
        private static final String END_POINT = "http://www.quanmin.tv/";
    
        DemoHttpClient mHttpClient;
    
        @Inject
        public DemoRetrofit(DemoHttpClient mHttpClient) {
            this.mHttpClient = mHttpClient;
        }
    
        @Override
        public ApiEndpoint getApiEndpoint() {
            return new ApiEndpoint() {
                @Override
                public String getEndpoint() {
                    return END_POINT;
                }
            };
        }
    
        @Override
        public OkHttpClient getHttpClient() {
            return mHttpClient.get();
        }
    }
    

    自定义数据返回解析器 GsonResponseBodyConverter.java; 其中实现了原始json输出。

    public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
        private final Gson gson;
        private final Type type;
    
        GsonResponseBodyConverter(Gson gson, Type type) {
            this.gson = gson;
            this.type = type;
        }
    
        @Override
        public T convert(ResponseBody value) throws IOException {
            String response = value.string();
            AppLog.i("<<<<<<<<<<<<<<<<<<<<<<<<<<<< Network response >>>>>>>>>>>>>>>>>>>>>>" + response);
            return gson.fromJson(response, type);
        }
    }
    

    ResponseConvertFactory.java

    
    public class ResponseConvertFactory extends Converter.Factory{
    
        /**
         * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
         * decoding from JSON (when no charset is specified by a header) will use UTF-8.
         */
        public static ResponseConvertFactory create() {
            return create(new Gson());
        }
    
        /**
         * Create an instance using {@code gson} for conversion. Encoding to JSON and
         * decoding from JSON (when no charset is specified by a header) will use UTF-8.
         */
        public static ResponseConvertFactory create(Gson gson) {
            return new ResponseConvertFactory(gson);
        }
    
        private final Gson gson;
        private ResponseConvertFactory(Gson gson) {
            if (gson == null) throw new NullPointerException("gson == null");
            this.gson = gson;
        }
    
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                                Retrofit retrofit) {
            return new GsonResponseBodyConverter<>(gson,type);
        }
    
    }
    

    2 添加repository包, 其中加入网络请求业务逻辑代码

    IMainService.java

    public interface IMainService {
        Observable<ResponseResult> getLiveListResult();
    }
    

    MainDataSource.java

    public class MainDataSource implements IMainService {
        
        
            @Inject
            Application mContext;
        
            MainApi maiApi;
        
            @Inject
            public MainDataSource(MainApi accountApi) {
                this.maiApi = accountApi;
            }
        
            @Override
            public Observable<ResponseResult> getLiveListResult() {
        
                return maiApi.getLiveListResult();
            }
        
        }
    

    ResponseObserver.java

    public abstract class ResponseObserver<T> extends Subscriber<T> {
        @Override
        public void onCompleted() {
        }
    
        @Override
        public void onNext(T t) {
            onSuccess(t);
        }
    
        public abstract void onSuccess(T t);
    }
    

    ResponseResult.java 返回值实体类

    public class ResponseResult {
        private int total;
        private int page;
        private int size;
        private String icon;
        private String pageCount;
    
        public int getTotal() {
            return total;
        }
    
        public void setTotal(int total) {
            this.total = total;
        }
    
        public int getPage() {
            return page;
        }
    
        public void setPage(int page) {
            this.page = page;
        }
    
        public int getSize() {
            return size;
        }
    
        public void setSize(int size) {
            this.size = size;
        }
    
        public String getIcon() {
            return icon;
        }
    
        public void setIcon(String icon) {
            this.icon = icon;
        }
    
        public String getPageCount() {
            return pageCount;
        }
    
        public void setPageCount(String pageCount) {
            this.pageCount = pageCount;
        }
    }
    
    • 加入完网络请求的业务逻辑, 我们在那里调用进行网络请求呢! 没错,我们只需要在MainPresenter中加入网络请求代码即可。
      最新MainPresenter.java代码如下:
    public class MainPresenter extends RxMvpPresenter<MainView> {
    
        private final IMainService mainService;
    
    
        @Inject
        public MainPresenter(IMainService mainService) {
            this.mainService = mainService;
        }
    
        @Inject
        Application context;
    
        public void getLiveListResult() {
            mCompositeSubscription.add(mainService.getLiveListResult()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .doOnSubscribe(new Action0() {
                        @Override
                        public void call() {
                            //加载中处理
                        }
                    })
                    .doOnTerminate(new Action0() {
                        @Override
                        public void call() {
                            //加载完成处理
                        }
                    })
                    .subscribe(new ResponseObserver<ResponseResult>() {
                        @Override
                        public void onSuccess(ResponseResult result) {
    
                            getMvpView().loginSuccess(result);
                        }
    
                        @Override
                        public void onError(Throwable e) {
                            e.printStackTrace();
                            getMvpView().loginException();
                        }
                    }));
        }
    }
    
    • 分别修改MainActivity.java 和MainView.java类
      MainActivity.java
    public class MainActivity extends BaseAcitvity implements MainView, HasComponent<MainComponent> {
    
        @BindView(R.id.test)
        TextView test;
    
        @Inject
        MainPresenter mainPresenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            getComponent().inject(this);
    
            //重要
            mainPresenter.attachView(this);
        }
    
    
        @OnClick(R.id.test)
        public void onClick() {
            mainPresenter.getLiveListResult();
        }
    
        @Override
        public void loginSuccess(ResponseResult result) {
            Toast.makeText(this, result.getIcon(), Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void loginFail() {
    
        }
    
        @Override
        public void loginException() {
    
        }
    
        @Override
        public MainComponent getComponent() {
            return DaggerMainComponent.builder()
                    .applicationComponent(Application.get(this).getComponent())
                    .activityModule(new ActivityModule(this))
                    .mainModule(new MainModule())
                    .build();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mainPresenter.detachView();
        }
    }
    

    MainView.java

    public interface MainView extends MvpView{
        void loginSuccess(ResponseResult result);
        void loginFail();
        void loginException();
    }
    
    • 运行代码,,,,发生了什么!!!没错就是报错了;;;

    3 解决报错问题

    • 该报错问题是由于MainService, MainApi没有交由Dagger2给提供给Presenter导致的。

    分别修改ApplicationModule.java、ApplicationComponent.java、MainModule.java

    ApplicationModule.java

    @Module
    public class ApplicationModule {
    
        protected final Application mApplication;
    
        public ApplicationModule(Application application) {
            mApplication = application;
        }
    
        @Provides
        public Application provideApplication() {
            return mApplication;
        }
    
        @Provides
        @ApplicationContext
        public Context provideContext() {
            return mApplication;
        }
    
        @Provides
        @Singleton
        public MainApi provideMainApi(DemoRetrofit retrofit) {
            return retrofit.get().create(MainApi.class);
        }
    }
    

    ApplicationComponent.java

    @Singleton
    @Component(modules = ApplicationModule.class)
    public interface ApplicationComponent {
        @ApplicationContext
        Context context();
    
        Application application();
    
        MainApi accountAccountApi();
    }
    

    MainModule.java

    @Module
    public class MainModule {
        @Provides
        public IMainService provideMainService(MainDataSource dataSource) {
            return dataSource;
        }
    
    }
    

    4 再次运行代码

    • 呵呵 成功了, 点击页面HelloWord 什么!!!没反应, 一顿狂点,还是没反应; 看一下后台, 报错了;原来是没有加入网络请求权限;;;网上copy一段网络请求权限代码防盗Manifests.xml文件中。再次运行。

    点击 页面Hello World; 运行如下; Toast弹出的即为从网络上请求得到的图片icon地址。

    ress.png

    项目下载地址

    相关文章

      网友评论

          本文标题:android MVP dagger2 Retrofit

          本文链接:https://www.haomeiwen.com/subject/ygfcrxtx.html