一俊啼、為什么要抽取左医?
- 每一個(gè)頁(yè)面都用到同樣的內(nèi)容授帕,每次都寫(xiě)同樣的代碼,浪費(fèi)浮梢;
- 規(guī)定代碼的編寫(xiě)規(guī)范跛十;
- 多人開(kāi)發(fā)維護(hù)變得簡(jiǎn)單。
二秕硝、抽取那些內(nèi)容
- 通用的操作
三芥映、設(shè)計(jì)模式
- 模板設(shè)計(jì)模式(讓子類(lèi)的工作模式都按照父類(lèi)的執(zhí)行)
- 單例設(shè)計(jì)模式
四、具體抽取
-
MVP抽取概述圖
image.png - 網(wǎng)絡(luò)抽取
- ①創(chuàng)建網(wǎng)絡(luò)管理類(lèi)远豺,使用雙檢索單例設(shè)計(jì)模式獲取對(duì)象
public class HttpUtil {
private static HttpUtil httpUtil;
public static HttpUtil getHttpUtil() {
if (httpUtil == null) {
synchronized (HttpUtil.class) {
if (httpUtil == null) {
httpUtil = new HttpUtil();
}
}
}
return httpUtil;
}
}
- ②在網(wǎng)絡(luò)管理器的構(gòu)造中獲取Retrofit的builder對(duì)象
public class HttpUtil {
private final Retrofit.Builder builder;
private HttpUtil() {
builder = new Retrofit.Builder()
.client(getHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
}
}
- ③使用泛型獲取ApiService對(duì)象
//一個(gè)返回T類(lèi)型的方法奈偏,T的類(lèi)型的泛型
public class HttpUtil {
public <T> T getService(String baseurl, Class<T> mClass) {
return builder.baseUrl(baseurl).build().create(mClass);
}
}
- ④自定義OKHTTPClient,設(shè)置超時(shí)躯护、請(qǐng)求頭惊来、攔截器等
public class HttpUtil {
private OkHttpClient getHttpClient() {
//設(shè)置本地緩存文件
File file = new File(Constants.PATH_CACHE);
//設(shè)置緩存
Cache cache = new Cache(file, 1024 * 1024 * 50);
//設(shè)置日志攔截器
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
} else {
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(httpLoggingInterceptor)
.addNetworkInterceptor(new MyCacheIntercepter())
.addInterceptor(new MyCacheIntercepter())
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build();
}
//網(wǎng)絡(luò)攔截器
public class MyCacheIntercepter implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!isNetworkAvailable(GeekApplication.getApplication())) {
request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
}
Response originalResponse = chain.proceed(request);
if (isNetworkAvailable(GeekApplication.getApplication())) {
int maxAge = 0;
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public ,max-age=" + maxAge)
.build();
} else {
int maxStale = 15 * 60;
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
}
public static boolean isNetworkAvailable(Context context) {
if (context != null) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
return info.isAvailable();
}
}
return false;
}
}
- ⑤抽取線程切換
public class RxUtil {
/**
* <T ,T > T轉(zhuǎn)換前的對(duì)象類(lèi)型, T 轉(zhuǎn)換后的對(duì)象類(lèi)型
*
* @param <T>
* @return
*/
public static <T> ObservableTransformer<T, T> rxObservableTransformer() {
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io());
}
};
}
}
- ⑥觀察者抽取
public abstract class BaseObserver<T> implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "訂閱成功");
}
@Override
public void onError(Throwable e) {
onFail("onError:" + e.getMessage());
}
@Override
public void onComplete() {
Log.e("TAG", "請(qǐng)求完成");
}
@Override
public void onNext(T value) {
onSuccess(value);
}
public abstract void onFail(String error);
protected abstract void onSuccess(T t);
}
- ⑦使用
HttpManager.getHttpManager().getApiService(ApiService.baseLoginUrl, ApiService.class)
.login(name, pwd)
.compose(RxUtil.<LoginBean>rxTransform())
.subscribe(new BaseObserver<LoginBean>() {
@Override
public void onSucess(LoginBean loginBean) {
if (loginBean.getErrorCode() == 0) {
callBack.onSucess(loginBean);
} else {
callBack.onFail(loginBean.getErrorMsg());
}
}
@Override
public void onFail(String error) {
callBack.onFail(error);
}
});
- BaseActivity抽取
public abstract class BaseActivity<P extends BasePresenter, V extends BaseView> extends AppCompatActivity {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
ButterKnife.bind(this);
mPresenter = initPresenter();
if (mPresenter != null) {
mPresenter.setmView(initMvpView());
}
initView();//有些子類(lèi)需要棺滞,有些不需要
initData();//有些子類(lèi)需要唁盏,有些不需要内狸,僅僅用普通方法即可
initListener();
}
protected abstract void initListener();
protected abstract void initData();
protected abstract void initView();
protected abstract V initMvpView();
protected abstract P initPresenter();
protected abstract int getLayoutId();
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.onDestory();
mPresenter = null;
}
}
- BaseModel抽取
public class BaseModel {
public CompositeDisposable mCompositeDisposable;
public void onDestory() {
//切斷所有的Disposable對(duì)象
if (mCompositeDisposable != null){
mCompositeDisposable.clear();
}
}
public void addDisposable(Disposable d){
if (mCompositeDisposable == null){
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(d);
}
}
- BaseView 抽取
public interface BaseView<T> {
void onSucess(T t);
void onFail(String error);
}
- BasePresenter抽取
public abstract class BasePresenter<V extends BaseView> {
protected V mView;
private ArrayList<BaseModel> mModels = new ArrayList<>();
public BasePresenter() {
initMdel();
}
protected abstract void initMdel();
public void setmView(V mView) {
this.mView = mView;
}
public void onDestory() {
//打斷P層和V層的聯(lián)系,
mView = null;
//掐斷網(wǎng)絡(luò)請(qǐng)求
if (mModels.size() > 0) {
for (BaseModel model : mModels) {
model.onDestory();
}
mModels.clear();
}
}
public void addModel(BaseModel model) {
mModels.add(model);
}
}
- callback抽取
public interface BaseCallBack<T> {
void onSuccess(T t);
void onFail(String error);
}
MVP抽取案例使用(登錄)
- M層
public class LoginModel extends BaseModel {
public void login(String name, String password, BaseCallBack<String, String> callBack) {
if (true) {
callBack.onSuccess("登錄成功");
} else {
callBack.onFail("登錄失敗");
}
}
}
- P層
public class LoginPresenter extends BasePresenter<LoginView, LoginModel> implements BaseCallBack<String, String> {
public void login(String name, String pwd) {
if (model != null) {
model .login(name, pwd, this);
}
}
@Override
public void onSuccess(String s) {
if (view != null) {
view .onSuccess(s);
}
}
@Override
public void onFail(String s) {
if (view != null) {
view .onFail(s);
}
}
}
- V層
public class MainActivity extends BaseActivity<LoginPresenter, LoginView, LoginModel> implements LoginView {
@BindView(R.id.btn_login)
Button btnLogin;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected LoginView initMvpView() {
return this;
}
@Override
protected LoginModel initMvpModel() {
return new LoginModel();
}
@Override
protected LoginPresenter initPresnter() {
return new LoginPresenter();
}
@Override
public void onSuccess(String s) {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
@Override
public void onFail(String s) {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
@OnClick({R.id.btn_login})
public void onViewClicked(View view) {
baseP.login("", "");
}
MVP與普通的分離(不需要mvp的頁(yè)面)
- 不需要MVP
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
ButterKnife.bind(this);
initMvp();
initView();//有些子類(lèi)需要,有些不需要
initData();//有些子類(lèi)需要厘擂,有些不需要,僅僅用普通方法即可
initListener();
}
private void initMvp() {}
protected abstract int getLayoutId();
private void initListener() {}
private void initData() {}
protected void initView() {}
}
- 需要mvp
public abstract class BaseMVPActivity<P extends BasePresenter, V extends BaseView, M extends BaseModel> extends BaseActivity {
protected P presenter;
@Override
public void initMvp() {
super.initMvp();
presenter = initPresnter();
if (presenter != null) {
presenter.addView(initMvpView());
presenter.addModel(initMvpModel());
}
}
protected abstract V initMvpView();
protected abstract M initMvpModel();
protected abstract P initPresnter();
}
Fragment抽取
- 沒(méi)有MVP抽取基類(lèi)
public abstract class BaseFragment extends Fragment {
private Unbinder unbinder;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(), container, false);
unbinder = ButterKnife.bind(this, view);
initMvp();
initView();
initData();
initListener();
return view;
}
protected void initMvp() {
}
protected void initListener() {
}
protected void initData() {
}
protected void initView() {
}
protected abstract int getLayoutId();
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}
- 有MVP抽取
public abstract class BaseMvpFragment<P extends BasePresenter, V extends BaseView, M extends BaseModel> extends BaseFragment {
protected P presenter;
@Override
protected void initMvp() {
super.initMvp();
presenter = initPresnter();
if (presenter != null) {
presenter.addView(initMvpView());
presenter.addModel(initMvpModel());
}
}
protected abstract V initMvpView();
protected abstract M initMvpModel();
protected abstract P initPresnter();
}
應(yīng)用崩潰問(wèn)題解決
- 背景:在發(fā)動(dòng)網(wǎng)絡(luò)請(qǐng)求的時(shí)候锰瘸,退出當(dāng)前activity
- 沖突:此時(shí)如果回到主線程更新UI刽严,APP會(huì)崩潰
- 解決:當(dāng)activity退出時(shí),調(diào)用DisPosable.dispose()切斷觀察者和被觀察者的連接避凝,使得觀察者無(wú)法收到事件&響應(yīng)事件舞萄;當(dāng)出現(xiàn)多個(gè)disposable時(shí),采用Rxjava內(nèi)置容器CompositeDisposable進(jìn)行統(tǒng)一管理
CompositeDisposable compositeDisposable = new CompositeDisposable()管削;
//添加disposable到CompositeDisposable容器
compositeDisposable .add();
//清空CompositeDisposable容器倒脓,在父類(lèi)的baseModel中調(diào)用
compositeDisposable .clear();
- 在BaseModel中
public abstract class BaseModel {
//用于統(tǒng)一切斷觀察者與被觀察者關(guān)系
CompositeDisposable compositeDisposable = new CompositeDisposable();
//切斷,P層調(diào)用
public void destroy() {
compositeDisposable.clear();
}
}
- 在basePresenter中
public class BasePresenter<V extends BaseView, M extends BaseModel> {
//創(chuàng)建一個(gè)集合含思,用于存放model
protected ArrayList<BaseModel> list = new ArrayList<BaseModel>();
protected V view;
protected M model;
public void addView(V v) {
this.view = v;
}
public void addModel(M m) {
this.model = m;
//添加model
list.add(m);
}
public void destroy() {
//如果view不為空崎弃,頁(yè)面關(guān)閉,強(qiáng)制置空含潘,否則內(nèi)存泄漏
if (view != null) {
view = null;
}
//如果頁(yè)面關(guān)閉饲做,切斷網(wǎng)絡(luò)請(qǐng)求的觀察者與被觀察者的關(guān)系
if (list.size() > 0) {
for (BaseModel baseModel : list) {
baseModel.destroy();
}
}
//如果model不為空,置空
if (model != null) {
model = null;
}
}
}
- 在BaseMVPActivity中
/**
* 頁(yè)面關(guān)閉時(shí)
* 切斷連接
* 內(nèi)存回收
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.destroy();
}
}