一 业务功能
二 问题
三 业务流程
1 初始化网络
2 测速选站点
3 拉取站点
4 手动切换站点
四 重点代码
public class StationMeasure {
private static final String TEST_STATION_URL = "/test/ips";
private static final String STATION_URL = "/product/ips";
private static final String URL = "url";
private static final String BASE_URL = "base_url";
private static final int TASK_TIME = 6;
private boolean isMeasuring = false;
private Disposable mGetServerTimer;
private int mGetServerStationStart;
private AtomicInteger mGetServerStationIndex;
private boolean isMeasureFirstBack = false;
private GetStationCallBack mStationCallBack;
protected CompositeDisposable disposables;
public void init() {
if (disposables != null) {
disposables.dispose();
}
disposables = new CompositeDisposable();
setStationByRandom();
disposables.add(Observable.timer(1, TimeUnit.SECONDS)
.subscribeWith(new SimpleDisposableObserver<Long>() {
@Override
public void onNext(Long aLong) {
startMeasureAutoChange();
}
}));
}
public void startMeasureAutoChange() {
synchronized (this) {
if (isMeasuring) {
return;
}
isMeasuring = true;
}
if (disposables != null) {
disposables.dispose();
}
disposables = new CompositeDisposable();
disposables.add(Observable.timer(TASK_TIME, TimeUnit.SECONDS)
.subscribeWith(new SimpleDisposableObserver<Long>() {
@Override
public void onNext(Long o) {
disposables.clear();
isMeasuring = false;
setStationByRandom();
}
}));
getStation(this::measure);
}
private void setStationByRandom() {
int len = Station.newInstance().getTcStations().length;
Station.newInstance().switchIp(new Random().nextInt(len));
}
private void measure(String[][] IPS) {
isMeasureFirstBack = false;
StringBuilder url;
for (int i = 0; i < IPS.length; i++) {
final int index = i;
url = new StringBuilder("http://").append(IPS[i][1]).append(":").append(IPS[i][2]);
Disposable disposable = getHttApi(url.toString())
.get(url.toString())
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribeWith(new SimpleDisposableObserver<ResponseBody>() {
@Override
public void onNext(ResponseBody responseBody) {
if (!isMeasureFirstBack) {
measureEnd(index);
}
}
});
disposables.add(disposable);
}
}
private void measureEnd(int index) {
isMeasureFirstBack = true;
isMeasuring = false;
disposables.clear();
Station.newInstance().switchIp(index);
}
private void getStation(GetStationCallBack callBack) {
mStationCallBack = callBack;
final int start = new Random().nextInt(Station.newInstance().getTcStations().length);
mGetServerStationIndex = new AtomicInteger();
mGetServerStationIndex.getAndSet(start);
mGetServerStationStart = start;
if (mGetServerTimer != null) {
mGetServerTimer.dispose();
}
mGetServerTimer = Observable.timer(3, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new SimpleDisposableObserver<Long>() {
@Override
public void onNext(Long aLong) {
if (mGetServerTimer != null) {
mGetServerTimer.dispose();
}
if (mStationCallBack != null) {
mStationCallBack.getStationCallBack(Station.newInstance().getTcStations());
mStationCallBack = null;
}
}
});
getIpFromServer();
}
private void getIpFromServer() {
String[][] openStation = Station.newInstance().getOpenStations();
Map<String, String> map = getUrlFormIp(openStation[mGetServerStationIndex.get() % openStation.length]);
getHttApi(map.get(BASE_URL)).get(map.get(URL))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SimpleDisposableObserver<ResponseBody>() {
@Override
public void onNext(ResponseBody responseBody) {
try {
String data = responseBody.string();
if (Station.newInstance().setStationFromData(data)) {
Station.newInstance().updateStationCache(data);
if (mStationCallBack != null) {
if (mGetServerTimer != null) {
mGetServerTimer.dispose();
}
mStationCallBack.getStationCallBack(Station.newInstance().getTcStations());
}
} else {
goOn();
}
} catch (Exception e) {
e.printStackTrace();
goOn();
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
goOn();
}
});
}
private Map<String, String> getUrlFormIp(String[] ips) {
Map<String, String> map = new HashMap<>();
try {
StringBuilder url = new StringBuilder("https://");
url.append(ips[1]);
url.append(":");
url.append(ips[2]);
map.put(BASE_URL, url.toString());
url.append(BuildConfig.DEBUG ? TEST_STATION_URL : STATION_URL);
map.put(URL, url.toString());
} catch (Exception e) {
e.printStackTrace();
goOn();
}
return map;
}
private void goOn() {
mGetServerStationIndex.getAndIncrement();
if (mGetServerStationIndex.get() >= Station.newInstance().getTcStations().length + mGetServerStationStart) {
if (mStationCallBack != null) {
mStationCallBack.getStationCallBack(Station.newInstance().getTcStations());
mStationCallBack = null;
if (mGetServerTimer != null) {
mGetServerTimer.dispose();
}
}
return;
}
getIpFromServer();
}
public static HttpApi getHttApi(String url) {
OkHttpClient.Builder builder = OKHttp.getOkHttpClient(3).newBuilder();
builder.addInterceptor(new CommonParamsInterceptor());
return new Retrofit.Builder()
.client(builder.build())
.baseUrl(url)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(HttpApi.class);
}
public static StationMeasure newInstance() {
return StationMeasureHolder.instance;
}
private StationMeasure() {
}
private static class StationMeasureHolder {
static StationMeasure instance = new StationMeasure();
}
private interface GetStationCallBack {
void getStationCallBack(String[][] IPS);
}
}