- How to design a good network framework, I have no answer in mind, I have seen a lot of other people’s wheels, some are too simple, limited too complex, some to meet the request of the network, praise or criticism
- The network framework of this article is based on the upgraded version of my network framework three years ago, please see MVP Network framework (Retorfit+Rxjava+Rxandroid) here.
Join the rely on
api "Com. Squareup. Retrofit2: retrofit: 2.5.0"
api "Com. Squareup. Retrofit2: converter - gson: 2.5.0"
api "Com. Squareup. Retrofit2: adapter - rxjava2:2.5.0"
api 'the IO. Reactivex. Rxjava2: rxandroid: 2.1.0'
api 'the IO. Reactivex. Rxjava2: rxjava: 2.2.2'
api "Com. Squareup. Okhttp3: logging - interceptor: 3.12.0"
Copy the code
rxjava
: is the reaction expansionJava VM
Implementation: a library for composing asynchronous and event-based programs using observable sequences.rxandroid
: This module addressesRxJava
Add the minimum number of classes so that theAndroid
Writing reactive components in your application is easy and hassle-free. More specifically, it is provided in the main thread or in anyLooper
The upper scheduler.converter-gson
Through:GsonConverterFactory
forRetrofit
addGson
supportlogging-interceptor
: You can intuitively observe the diary of network requests
adapter-rxjava2
: One for adaptationRXJava 2
Type of adapter.
Build a Network Framework
- IMvpView
* @param errorCode * @param errorMsg */ void getDataFail(String errorCode, String errorMsg); @param e */ void onError(Throwable e); }Copy the code
- IPresenter processing and View lifecycle
Public interface IPresenter<V extends IMvpView> {@param mvpView */ void attachView(V mvpView); /* detachView(); /* detachView(); }Copy the code
BasePresenter
allPresenter
Base class, and bind allActivity
Life cycle of
public class BasePresenter<V extends IMvpView> implements IPresenter<V> {
private V mMvpView;
@Override
public void attachView(V mvpView) {
mMvpView = mvpView;
}
@Override
public void detachView() { mMvpView = null; } /** * determine whether the * @ is still connectedreturn
*/
public boolean isViewAttached() {
returnmMvpView ! = null; } public VgetMvpView() {
returnmMvpView; } /** * Check if the View is attached */ public voidcheckViewAttached() {
if(! isViewAttached()) throw new MvpViewNotAttachedException(); } public static class MvpViewNotAttachedException extends RuntimeException { publicMvpViewNotAttachedException() {
super("Make sure you bind views before you bind data."); }} /** * This is the onServer in the Observer, when we call this method, * @disposable */ public void dispose(disposable disposable) {if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}
Copy the code
- General structure drawing
The network framework DataManager
- According to the design ideas of the previous articleHement MVP Architecture Design (1)
- You can know
DataManager
Not only do you need to handle network requests, but you also need to handle local storageSharedPreferences
andSQLite
- So instead, the DataManager provides data objects to the outside world. The processing of the data is already done for you. When you use the data, you just need to get the object instance you want
@Singleton
public class DataManager {
private final IRemoteServer mIRemoteServer;
private final PreferencesHelper mPreferencesHelper;
private final DatabaseHelper mDatabaseHelper;
@Inject
public DataManager(IRemoteServer server, PreferencesHelper preferencesHelper, DatabaseHelper databaseHelper) {
mIRemoteServer = server;
mPreferencesHelper = preferencesHelper;
mDatabaseHelper = databaseHelper;
}
public void loadData(String key, String day, BaseObserver observer) {
Observable<SMResponse<ArrayList<TodayBean>>> today = mIRemoteServer.getToday(key, day);
today.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(observer);
}
public PreferencesHelper getPreferencesHelper() {
returnmPreferencesHelper; } /** * fetch data from the network, cache it to the database, and fetch data from the database * @return
*/
public Observable<TodayBean> syncDBBean() {
return mIRemoteServer.getToday("b15674dbd34ec00ded57b369dfdabd90"."1/1").concatMap(new Function<SMResponse<ArrayList<TodayBean>>, ObservableSource<? extends TodayBean>>() {
@Override
public ObservableSource<? extends TodayBean> apply(@NonNull SMResponse<ArrayList<TodayBean>> response)
throws Exception {
returnmDatabaseHelper.setDBData(response.result); }}); } /** * fetch data from the database * @return
*/
public Observable<List<TodayBean>> getDBBean() {
returnmDatabaseHelper.getDBData().distinct(); }}Copy the code
How is the network framework used
- Here is the use of aggregated data interface, here thanks to the selfless contribution, three years of this interface can still be used, very grateful
http://v.juhe.cn/todayOnhistory/queryEvent.php?key=b15674dbd34ec00ded57b369dfdabd90&date=1/1
Copy the code
- 1, Define the remote Server:
IRemoteServer
I’m going to take the previous one and generate it separatelyRetrofit
theServer
Drawn to theIRemoteServer
Because the project usesDagger2
, introduced later
public interface IRemoteServer { /** * The key * http://v.juhe.cn/todayOnhistory/queryEvent.php?key=b15674dbd34ec00ded57b369dfdabd90&date=1/1 * @ param key application @param date Date * @returnReturn to today in history */ @get ("queryEvent.php")
Observable<SMResponse<ArrayList<TodayBean>>> getToday(@Query("key") String key, @Query("date") String date);
class Creator {
public static IRemoteServer newHementService() {
returnSMRetrofit.getService(HementApplication.getContext(), IRemoteServer.class); }}}Copy the code
- 2,
DataManager
The result is called back toAndroidSchedulers.mainThread()
Threads, that’s androidUI
Threads.
private final IRemoteServer mIRemoteServer;
private final PreferencesHelper mPreferencesHelper;
private final DatabaseHelper mDatabaseHelper;
@Inject
public DataManager(IRemoteServer server, PreferencesHelper preferencesHelper, DatabaseHelper databaseHelper) {
mIRemoteServer = server;
mPreferencesHelper = preferencesHelper;
mDatabaseHelper = databaseHelper;
}
public void loadData(String key, String day, BaseObserver observer) {
Observable<SMResponse<ArrayList<TodayBean>>> today = mIRemoteServer.getToday(key, day);
today.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(observer);
}
Copy the code
- 3,
NetWorkPresenter
define
@ConfigPersistent
public class NetWorkPresenter extends BasePresenter<NetWorkView> {
private final DataManager mDataManager;
private Disposable mDisposable;
@Inject
public NetWorkPresenter(DataManager dataManager) {
mDataManager = dataManager;
}
@Override
public void attachView(NetWorkView mvpView) {
super.attachView(mvpView);
}
@Override
public void detachView() {
super.detachView();
if(mDisposable ! = null) mDisposable.dispose(); } public void loadData(String key,String day){// Check whether the View is attached to it. Dispose (mDisposable) dispose(mDisposable) mDataManager.loadData(key,day,new BaseObserver<SMResponse<ArrayList<TodayBean>>>(new SubscriberListener<SMResponse<ArrayList<TodayBean>>>() { @Override public void onSubscribe(Disposable disposable) { super.onSubscribe(disposable); mDisposable = disposable; } @Override public void onSuccess(SMResponse<ArrayList<TodayBean>> response) { getMvpView().getDataSuccess(response.result); } @Override public void onFail(String errorCode, String errorMsg) { getMvpView().getDataFail(errorCode,errorMsg); } @Override public void onError(Throwable e) { getMvpView().onError(e); }})); }}Copy the code
- 4, in
Activity
Through Dagger2 dependency injectionNetWorkPresenter
And at the same timeonDestroy()
The destruction ofRxJava2
If the Activity is shut down, the network request may be in progress, so it needs to be destroyed.
public class NetWorkActivity extends BaseActivity implements NetWorkView, View.OnClickListener {
String key="b15674dbd34ec00ded57b369dfdabd90";
@Inject
NetWorkPresenter mMainPresenter;
private Button mBtn;
private EditText mDay;
private EditText mMonth;
private RecyclerView mRecyclerView;
private SMAdapter mSmAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityComponent().inject(this);
setContentView(R.layout.activity_net_work);
Timber.tag(getClassName()).i("mMainPresenter =%s",mMainPresenter);
mMainPresenter.attachView(this);
initView();
initListener();
}
private void initView() {
mBtn = (Button) findViewById(R.id.btn);
mMonth = (EditText) findViewById(R.id.et_month);
mDay = (EditText) findViewById(R.id.et_day);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
}
private void initListener() {
mBtn.setOnClickListener(this);
mSmAdapter = new SMAdapter(this, null);
mRecyclerView.setAdapter(mSmAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
@Override
public void getDataFail(String errorCode, String errorMsg) {
Toast.makeText(this,errorMsg+errorCode,Toast.LENGTH_LONG).show();
}
@Override
public void onError(Throwable e) {
Toast.makeText(this,e.toString(),Toast.LENGTH_LONG).show();
}
@Override
public void getDataSuccess(ArrayList<TodayBean> result) {
String s = new Gson().toJson(result);
Timber.tag(getClassName()).i(s);
Thread thread = Thread.currentThread();
Timber.tag(getClassName()).i(thread.toString());
mSmAdapter.addData(result);
}
@Override
protected void onDestroy() {
super.onDestroy();
mMainPresenter.detachView();
}
@Override
public void onClick(View v) {
if (TextUtils.isEmpty(mMonth.getText())||TextUtils.isEmpty(mDay.getText())){
Toast.makeText(NetWorkActivity.this,"Can't be empty.",Toast.LENGTH_SHORT).show();
}else {
mMainPresenter.loadData(key,mMonth.getText()+"/"+mDay.getText()); }}}Copy the code
-
To be continued to the next article
-
GitHub address: Hement: Updates continuously