android MVP + dagger2 + Retrofit + Rxjava+okhttp android基础项目框架搭建(3)--完美实现

前面两片文章中已经完成了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地址。
                                                                                                 


项目下载地址

猜你喜欢

转载自blog.csdn.net/lg878398509/article/details/77018488