RxJava,Retrofit,OkHttp3結合使用
阿新 • • 發佈:2019-01-10
首先 亮出 gradle
其次亮出程式碼結構apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { applicationId "com.github.jtml" minSdkVersion 16 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.2.0' compile 'com.android.support:support-v4:23.2.1' compile 'com.android.support:recyclerview-v7:23.2.1' compile 'com.android.support:cardview-v7:23.2.1' compile 'com.android.support:design:23.2.1' // retrofit2 + okhttp3 compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okhttp3:logging-interceptor:3.2.0' // rxjava compile 'io.reactivex:rxandroid:1.1.0' compile 'io.reactivex:rxjava:1.1.0' // gson react compile 'com.google.code.gson:gson:2.6.2' compile 'com.jakewharton:butterknife:7.0.1' compile project(':pulltorefresh_lib') compile 'com.android.support:support-v13:+' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.yalantis:phoenix:1.2.3' }
- activitys - MainActivity.java
- fragment - BuyGoodFragment.java
- network - factory - MyCustomFactory.java
- network - factory - UserResponseConverter.java
- network - manager - MyRetrofitConverter.java
- network - service - JtmlServer.java
最後亮出程式碼
package com.github.jtml.network.factory; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import okhttp3.ResponseBody; import retrofit2.Converter; import retrofit2.Retrofit; /** * Created by pengjf on 2016/5/12. */ public class MyCustomFactory extends Converter.Factory { @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { //根據type判斷是否是自己能處理的型別,不能的話,return null ,交給後面的Converter.Factory return new UserResponseConverter(type); } }
package com.github.jtml.network.factory; import com.google.gson.Gson; import java.io.IOException; import java.lang.reflect.Type; import okhttp3.ResponseBody; import retrofit2.Converter; /** * Created by pengjf on 2016/5/12. */ public class UserResponseConverter<T> implements Converter<ResponseBody, T> { private Type type; Gson gson = new Gson(); public UserResponseConverter(Type type) { this.type = type; } @Override public T convert(ResponseBody responseBody) throws IOException { String result = responseBody.string(); T users = gson.fromJson(result, type); return users; } }
package com.github.jtml.network.manager;
import com.github.jtml.App;
import com.github.jtml.bean.Comment;
import com.github.jtml.bean.GoodsDetail;
import com.github.jtml.bean.GoodsList;
import com.github.jtml.bean.IndexImgList;
import com.github.jtml.bean.Notifications;
import com.github.jtml.bean.ShowBill;
import com.github.jtml.network.service.JtmlServer;
import com.github.jtml.utils.NetUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
/**
* Created by pengjf on 2016/5/12.
*/
public class MyRetrofitManager {
public static final String BASE_NIUPAI_URL = "private url1";
public static final String BASE_IMAGE_URL = "private url2";
//短快取有效期為1秒鐘
public static final int CACHE_STALE_SHORT = 1;
//長快取有效期為7天
public static final int CACHE_STALE_LONG = 60 * 60 * 24 * 7;
public static final String CACHE_CONTROL_AGE = "Cache-Control: public, max-age=";
//查詢快取的Cache-Control設定,為if-only-cache時只查詢快取而不會請求伺服器,max-stale可以配合設定快取失效時間
public static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_LONG;
//查詢網路的Cache-Control設定,頭部Cache-Control設為max-age=0時則不會使用快取而請求伺服器
public static final String CACHE_CONTROL_NETWORK = "max-age=0";
private static OkHttpClient mOkHttpClient;
private final JtmlServer mJtmlService;
public static MyRetrofitManager builder() {
return new MyRetrofitManager();
}
private MyRetrofitManager() {
initOkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_NIUPAI_URL)
.client(mOkHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
// .addConverterFactory(new MyCustomFactory())
.addConverterFactory(GsonConverterFactory.create())
.build();
mJtmlService = retrofit.create(JtmlServer.class);
}
private void initOkHttpClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
if (mOkHttpClient == null) {
synchronized (MyRetrofitManager.class) {
if (mOkHttpClient == null) {
// 指定快取路徑,快取大小100Mb
Cache cache = new Cache(new File(App.getContext().getCacheDir(), "HttpCache"),
1024 * 1024 * 100);
mOkHttpClient = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(mRewriteCacheControlInterceptor)
.addNetworkInterceptor(mRewriteCacheControlInterceptor)
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.build();
}
}
}
}
// 雲端響應頭攔截器,用來配置快取策略
private Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!NetUtil.isNetworkConnected()) {
request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
}
Response originalResponse = chain.proceed(request);
if (NetUtil.isNetworkConnected()) {
//有網的時候讀介面上的@Headers裡的配置,你可以在這裡進行統一的設定
String cacheControl = request.cacheControl().toString();
return originalResponse.newBuilder().header("Cache-Control", cacheControl).removeHeader("Pragma").build();
} else {
return originalResponse.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_LONG).removeHeader("Pragma").build();
}
}
};
public Observable<List<Comment>> getComments() {
return mJtmlService.getComments();
}
public Observable<List<Notifications>> getNotifications() {
return mJtmlService.getNotifications();
}
public Observable<List<ShowBill>> getShareBills(String id, String pageNo, String pageSize) {
return mJtmlService.getShareBills(id, pageNo, pageNo);
}
public Observable<GoodsDetail> getGoodsDetailById(String id) {
return mJtmlService.getGoodsDetailById(id);
}
public Observable<List<IndexImgList>> getIndexImgList() {
return mJtmlService.getIndexImgList();
}
public Observable<ArrayList<GoodsList>> getGoodList(String id, String pageNo, String pageSize) {
return mJtmlService.getGoodList(id, pageNo, pageSize);
}
}
package com.github.jtml.network.service;
import com.github.jtml.bean.Comment;
import com.github.jtml.bean.GoodsDetail;
import com.github.jtml.bean.GoodsList;
import com.github.jtml.bean.IndexImgList;
import com.github.jtml.bean.Notifications;
import com.github.jtml.bean.ShowBill;
import com.github.jtml.network.manager.MyRetrofitManager;
import java.util.ArrayList;
import java.util.List;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Query;
import rx.Observable;
/**
* Created by pengjf on 2016/5/12.
*/
public interface JtmlServer {
//評論介面
@Headers(MyRetrofitManager.CACHE_CONTROL_AGE + MyRetrofitManager.CACHE_STALE_SHORT)
@GET("share/indexSharecommentsList.action")
Observable<List<Comment>> getComments();
//最新揭曉介面
@Headers(MyRetrofitManager.CACHE_CONTROL_AGE + MyRetrofitManager.CACHE_STALE_SHORT)
@GET("lottery/lotteryproductutilList.action")
Observable<List<Notifications>> getNotifications();
//商品詳情介面
@Headers(MyRetrofitManager.CACHE_CONTROL_AGE + MyRetrofitManager.CACHE_STALE_SHORT)
@GET("products/goodsDescAjax.action")
Observable<GoodsDetail> getGoodsDetailById(@Query("id") String id);
//晒單介面
@Headers(MyRetrofitManager.CACHE_CONTROL_AGE + MyRetrofitManager.CACHE_STALE_SHORT)
@GET("share/ajaxPage.action")
Observable<List<ShowBill>> getShareBills(@Query("id") String id, @Query("pageNo") String pageNo, @Query("pageSize") String pageSize);
//主頁面輪播圖介面
@Headers(MyRetrofitManager.CACHE_CONTROL_AGE + MyRetrofitManager.CACHE_STALE_SHORT)
@GET("list/indexImgList.action")
Observable<List<IndexImgList>> getIndexImgList();
//主頁面商品列表介面
@Headers(MyRetrofitManager.CACHE_CONTROL_AGE + MyRetrofitManager.CACHE_STALE_SHORT)
@GET("list/goodsList.action")
Observable<ArrayList<GoodsList>> getGoodList(@Query("id") String id, @Query("pageNo") String pageNo, @Query("pageSize") String pageSize);
}
package com.github.jtml.ui.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.github.jtml.App;
import com.github.jtml.R;
import com.github.jtml.base.BaseActivity;
import com.github.jtml.base.BaseRecyclerAdapter;
import com.github.jtml.bean.GoodsDetail;
import com.github.jtml.network.manager.MyRetrofitManager;
import com.github.jtml.ui.adapter.GoodsDetailAdapter;
import com.github.jtml.ui.view.Kanner;
import com.github.jtml.ui.view.RecyclerViewBaseOnPullToRefresh;
import com.github.jtml.utils.L;
import butterknife.Bind;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
/**
* Created by pengjf on 2016/5/12.
*/
public class GoodsDetailActivity extends BaseActivity {
@Bind(R.id.activity_goosdetail_img_back)
ImageView mImgBack;
@Bind(R.id.activity_goosdetail_img_share)
ImageView mImgShare;
@Bind(R.id.activity_goosdetail_img_cart)
ImageView mImgCart;
@Bind(R.id.activity_goosdetail_img_home)
ImageView mImgHome;
@Bind(R.id.activity_goosdetail_rv_detail)
RecyclerViewBaseOnPullToRefresh mRvDetail;
@Bind(R.id.activity_goosdetail_ll_unsell)
LinearLayout mLlUnsell;
@Bind(R.id.activity_goosdetail_ll_selling)
LinearLayout mLlSelling;
@Bind(R.id.activity_goosdetail_buy_now)
TextView mTxtBuyNow;
@Bind(R.id.activity_goosdetail_add_bill)
TextView mTxtAddBill;
@Bind(R.id.activity_goosdetail_go_now)
TextView mTxtGoNow;
public final static String LOTTERY_ID = "lotteryProductId";
public final static String INTENT_FROM = "intentFrom";
private String lotteryProductId;
private String intentFrom;
private Context mContext;
private App app;
private RecyclerView.LayoutManager mLayoutManager;
private GoodsDetailAdapter mGoodsDetailAdapter;
private View mHeadView;
private Kanner mKanner;
public static void start(Context context, String lotteryProductId, String intentFrom) {
Intent intent = new Intent(context, GoodsDetailActivity.class);
intent.putExtra(LOTTERY_ID, lotteryProductId);
intent.putExtra(INTENT_FROM, intentFrom);
context.startActivity(intent);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(LOTTERY_ID, this.lotteryProductId);
outState.putString(INTENT_FROM, this.intentFrom);
}
@Override
protected int getLayoutId() {
return R.layout.activity_goods_detail;
}
@Override
protected void afterCreate(Bundle savedInstanceState) {
mContext = this;
app = (App) mContext.getApplicationContext();
app.addClearActivity(this);
initData(savedInstanceState);
loadGoodsDetailById();
}
private void initData(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.containsKey(LOTTERY_ID) && savedInstanceState.containsKey(INTENT_FROM)) {
this.lotteryProductId = savedInstanceState.getString(LOTTERY_ID);
this.intentFrom = savedInstanceState.getString(INTENT_FROM);
}
}else{
this.lotteryProductId = getIntent().getExtras().getString(LOTTERY_ID);
this.intentFrom = getIntent().getExtras().getString(INTENT_FROM);
}
mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRvDetail.getRefreshableView().setLayoutManager(mLayoutManager);
mRvDetail.getRefreshableView().setItemAnimator(new DefaultItemAnimator());
mGoodsDetailAdapter = new GoodsDetailAdapter();
setHeader(mRvDetail.getRefreshableView());
mRvDetail.getRefreshableView().setAdapter(mGoodsDetailAdapter);
mGoodsDetailAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, Object data) {
}
});
//showNewsDetailFragment(news);
}
private void setHeader(RecyclerView view) {
View header = LayoutInflater.from(this).inflate(R.layout.item_good_detail_first, view, false);
mHeadView = header;
mGoodsDetailAdapter.setHeaderView(header);
}
private void loadGoodsDetailById() {
MyRetrofitManager.builder().
getGoodsDetailById(this.lotteryProductId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Action0() {
@Override
public void call() {
// showProgress();
}
}).map(new Func1<GoodsDetail, GoodsDetail>() {
@Override
public GoodsDetail call(GoodsDetail goodsDetail) {
L.e(goodsDetail.getId());
return goodsDetail;
}
}).subscribe(new Action1<GoodsDetail>() {
@Override
public void call(GoodsDetail goodsDetail) {
L.e(goodsDetail.getId());
}
},new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
L.e(throwable,"Load news detail error");
}
});
}
}
package com.github.jtml.ui.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.github.jtml.App;
import com.github.jtml.R;
import com.github.jtml.base.BaseFragment;
import com.github.jtml.bean.GoodsList;
import com.github.jtml.bean.IndexImgList;
import com.github.jtml.network.manager.MyRetrofitManager;
import com.github.jtml.ui.adapter.GoodListAdapter;
import com.github.jtml.ui.view.Kanner;
import com.github.jtml.ui.view.RecyclerViewBaseOnPullToRefresh;
import com.github.jtml.utils.L;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
/**
* Created by pengjf on 2016/5/12.
*/
public class FragmentBuyGood extends BaseFragment {
@Bind(R.id.fragment_buy_txt_title)
TextView mTxtTitle;
@Bind(R.id.fragment_buy_img_search)
ImageView mImgSearch;
@Bind(R.id.fragment_buy_rv_goods)
RecyclerViewBaseOnPullToRefresh mBuyRv;
Kanner mKanner;
private App app;
private Context mContext;
private RecyclerView.LayoutManager mLayoutManager;
private GoodListAdapter mGoodListAdapter;
private String[] imgUrls; //輪播圖需要的url陣列
private String id = "hot20"; //商品預設查詢id
private String typeId; //商品預設分類id
private String pageNo = "0"; //商品預設頁數
private String pageSize = "10"; //商品預設每頁個數
@Override
protected int getLayoutId() {
return R.layout.fragment_buy_good;
}
@Override
protected void afterCreate(Bundle savedInstanceState) {
mContext = getActivity();
app = (App) mContext.getApplicationContext();
initData();
// if (mNewsListAdapter.getmNewsList().size() == 0) {
// loadLatestNews();
// }
}
public static FragmentBuyGood newInstance() {
return new FragmentBuyGood();
}
private void initData() {
mLayoutManager = new GridLayoutManager(mContext, 2);
mGoodListAdapter = new GoodListAdapter();
mBuyRv.getRefreshableView().setLayoutManager(mLayoutManager);
// mBuyRv.getRefreshableView().setItemAnimator(new DefaultItemAnimator());
// mBuyRv.getRefreshableView().addItemDecoration(new GridItemDecoration(mContext, true));
mBuyRv.getRefreshableView().setAdapter(mGoodListAdapter);
setHeader(mBuyRv.getRefreshableView());
loadHeaderViewData();
loadGoodListData();
}
/**
* 給RecycleView設定頭部的View
* @param view
*/
private void setHeader(RecyclerView view) {
View header = LayoutInflater.from(mContext).inflate(R.layout.item_fragment_buy_frist, view, false);
mKanner = (Kanner) header.findViewById(R.id.fragment_buy_kanner);
mKanner.setVisibility(View.VISIBLE);
mGoodListAdapter.setHeaderView(header);
}
/**
* 載入RecycleView頭部的View需要的資料
*/
private void loadHeaderViewData() {
MyRetrofitManager.builder().getIndexImgList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Action0() {
@Override
public void call() {
// showProgress();
}
}).map(new Func1<List<IndexImgList>, List<IndexImgList>>() {
@Override
public List<IndexImgList> call(List<IndexImgList> result) {
return result;
}
})
.subscribe(new Action1<List<IndexImgList>>() {
@Override
public void call(List<IndexImgList> result) {
if(result!=null && result.size()>0) {
imgUrls = new String[result.size()];
for (int i = 0; i < result.size(); i++) {
imgUrls[i] = MyRetrofitManager.BASE_IMAGE_URL + result.get(i).getProImg();
}
mKanner.setImagesUrl(imgUrls);
}else{ //伺服器返回資料異常情況待處理
}
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
//mAutoLoadListener.setLoading(false);
L.e(throwable, "Load before news error");
throwable.printStackTrace();
//mLoadBeforeSnackbar.show();
}
});
}
private void loadGoodListData() {
MyRetrofitManager.builder().getGoodList(this.id,this.pageNo,this.pageSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Action0() {
@Override
public void call() {
// showProgress();
}
}).map(new Func1<ArrayList<GoodsList>, ArrayList<GoodsList>>() {
@Override
public ArrayList<GoodsList> call(ArrayList<GoodsList> result) {
return result;
}
})
.subscribe(new Action1<ArrayList<GoodsList>>() {
@Override
public void call(ArrayList<GoodsList> result) {
//伺服器成功返回資料
if(result!=null && result.size()>0) {
mGoodListAdapter.addDatas(result);
}else{ //伺服器返回資料異常情況待處理
}
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
//mAutoLoadListener.setLoading(false);
L.e(throwable, "Load before news error");
throwable.printStackTrace();
//mLoadBeforeSnackbar.show();
}
});
}
}