App项目架构
来公司实习的第二个月,开始了人生的第二个项目。因为项目大,所以是多人合作,于是乎终于摆脱了在学校的那种跟着功能走的处境,有大佬搭了一个简易的框架于是乎学习了一番
项目总览
好像上传不了照片,那就一点一点的说吧
1.netService包
这个包用于网络上传
Server.class 这个类的作用是用于存放整个项目所用到的接口地址
public class Server {
public static final String getUserInfo = "/teacher-api/images/labels";
}
RetrofitService.class是引用Server.class的地址的retrofit的类
public interface RetrofitService {
@GET(Server.getUserInfo)
Flowable<BaseRsp> getUserInfo();
}
RetrofitHelper
它的作用通过单例模式获得到retrofitService的实际操作对象
package com.example.yangyang.mvpproject.netService;
import com.example.yangyang.mvpproject.BuildConfig;
import com.google.gson.GsonBuilder;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitHelper {
public static final String BASE_URL = "http://www.baidu.com";
private static RetrofitHelper retrofitHelper = null;
private RetrofitService retrofitService = null;
private RetrofitHelper(){
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(BASE_URL)
.client(HttpsFactroy.getClient())
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
retrofitService = retrofit.create(RetrofitService.class);
}
public static RetrofitHelper getInstance(){
if(retrofitHelper == null){
synchronized (RetrofitHelper.class){
if(retrofitHelper == null){
retrofitHelper = new RetrofitHelper();
}
}
}
return retrofitHelper;
}
public RetrofitService getRetrofitService(){
return retrofitService;
}
}
HttpsFactroy.class这个类的作用是用于得到client,同时自定义的拦截器,可以动态的在http请求中添加一些东西,比如token,同时导入一些第三方库,可以加入http的日志拦截器
package com.example.yangyang.mvpproject.netService;
import android.util.Log;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
public class HttpsFactroy {
private static final int CONNECT_TIMEOUT = 10;
private static final int READ_TIMEOUT = 10;
//得到请求client
public static OkHttpClient getClient(){
//日志显示级别
HttpLoggingInterceptor.Level level= HttpLoggingInterceptor.Level.BODY;
//新建log拦截器
HttpLoggingInterceptor loggingInterceptor=new HttpLoggingInterceptor(message -> Log.i("HTTPS","OkHttp====Message:"+message));
loggingInterceptor.setLevel(level);
OkHttpClient client = null;
try {
client = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor(new HeaderIntercepter())
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT,TimeUnit.SECONDS)
.build();
} catch (Exception e) {
Log.e("error", Log.getStackTraceString(e));
}
return client;
}
/**
* 用于动态添加header
*/
private static class HeaderIntercepter implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain
.request()
.newBuilder()
/*.addHeader()*/
.build();
return chain.proceed(request);
}
}
}
DataManager.class
这个类是最后retrofit的入口,管理所有的http请求,其实说白了,知道retrofit怎么用,这几个类都是对retrofit调用的一些封装
package com.example.yangyang.mvpproject.netService;
import com.example.yangyang.mvpproject.base.BaseRsp;
import io.reactivex.Flowable;
public class DataManager {
private RetrofitService mRetrofitService;
public DataManager(){
mRetrofitService = RetrofitHelper.getInstance().getRetrofitService();
}
public Flowable<BaseRsp> getUserInfo(){
return mRetrofitService.getUserInfo();
}
}
同时因为用的是rxjava,所以flowable之后得有一个下游的管道去接它,同时接数据的时候也得有一个回调,所以在callback包里面就有一个整体的回调
2.callback
先上代码
RequestCallBack.class
package com.example.yangyang.mvpproject.callback;
import android.util.Log;
import com.example.yangyang.mvpproject.base.BaseRsp;
import org.apache.http.conn.ConnectTimeoutException;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Locale;
import javax.net.ssl.SSLException;
import io.reactivex.exceptions.OnErrorNotImplementedException;
import io.reactivex.subscribers.DisposableSubscriber;
import retrofit2.adapter.rxjava2.HttpException;
public abstract class RequestCallBack<T> extends DisposableSubscriber<BaseRsp<T>> {
@Override
public void onNext(BaseRsp<T> tBaseRsp) {
if (tBaseRsp.getCode() == 200) {
onReqSuccess(tBaseRsp.getData());
}
else {
onBizError(tBaseRsp.getCode(),tBaseRsp.getMsg());
}
}
@Override
public void onError(Throwable e) {
String msg;
if ((e instanceof HttpException)) {
msg = ((retrofit2.HttpException) e).message();
onNetError(((retrofit2.HttpException) e).code(), msg);
} else if (e instanceof UnknownHostException) {
msg = "域名解析失败";
onNetError(-1001,msg);
} else if (e instanceof ConnectTimeoutException) {
msg = "连接超时";
onNetError(-1002,msg);
} else if (e instanceof SocketTimeoutException) {
msg = "Socket连接超时";
onNetError(-1003,msg);
} else if (e instanceof NoRouteToHostException) {
msg = "无法连接远程地址与端口";
onNetError(-1004,msg);
} else if (e instanceof SSLException) {
msg = "SSL失败";
onNetError(-1005,msg);
} else if (e instanceof ConnectException) {
msg = "连接失败";
onNetError(-1006,msg);
} else if (e instanceof retrofit2.HttpException) {
retrofit2.HttpException exception = (retrofit2.HttpException) e;
msg = exception.message();
Log.d("HttpException",msg);
onNetError(exception.code(),msg);
} else if (e instanceof OnErrorNotImplementedException) {
msg = e.getMessage();
onNetError(-1007, msg);
}
else {
msg = "网络请求出错";
onNetError(-1009, msg);
}
}
@Override
public void onComplete() {
}
protected abstract void onReqSuccess(T t);
//业务错误
protected abstract void onBizError(int code, String msg);
//网络错误
protected abstract void onNetError(int code, String msg);
}
DisposableSubscriber其实我也不太了解具体,就当他是一个观察者吧,<BaseRsp<T>这些事前后台带的一些数据其实也可以带json数据然后自己来解析也可以的,同时最下面有3个抽象函数,分别对应成功了干啥,这些具体的回调函数的实现是放在p层实现的,p层再根据结果回调v层的方法
以上便是网络层的封装
2.mvp
-M层
一般来说我是一个activity一个model,如果两个不同activity调用同一个接口,此时我会提取公共model,让需要这个功能的人去继承它,M层的功能就是进行数据转化,同时将requestcall返回给p层
public class LoginModel {
private DataManager manager;
public LoginModel(DataManager manager) {
this.manager = manager;
}
private RequestCallBack getUserInfo(RequestCallBack callBack){
manager.getUserInfo()
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(callBack);
return callBack;
}
}
-P层
首先有一个BasePresenter,大家都知道的它的作用莫不过在于拿到V层的实例,以及要返回的数据
BasePresenter
package com.example.yangyang.mvpproject.mvp.presenter.base;
import com.example.yangyang.mvpproject.mvp.view.contract.base.BaseView;
public class BasePresenter <V extends BaseView , T > {
protected V mview = null;
public BasePresenter(V mview) {
this.mview = mview;
}
}
为什么会有泛型了,因为P层得持有V层的引用,但是并不知道V是哪个,所以加入V层泛型便能得到类型,但是后面接着的那个T其实可用可不用,删掉也没关系。因为T是从网络端返回的数据类型,在RequestCall中我们已经定义好了其类型,而且P层接Model层,M层接RequestCall中的泛型,所以删除掉也可以的
BaseView
package com.example.yangyang.mvpproject.mvp.view.contract.base;
public interface BaseView {
void showProgress();
void dismissProgress();
}
这是在contract包中的base,contract包分为两个,一个是V层接口,一个是impl包放的是activity和fragment的实现,所以V extend BaseView ,activity和fragment实现这个V,但是其实BaseView的方法其实是共有的,其实是可以让BaseActivity实现的,不用每个Activity或者fragment实现的,但有丢丢神奇的是,这个框架在BaseActivity中实现具体的 showProgress()和 dismissProgress();在每个activity中调用其方法,好吧,这样也可以,
以上就是mvp的实现
3.BaseActivity
BaseActivity
package com.example.yangyang.mvpproject.mvp.view.impl.activity.base;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.example.yangyang.mvpproject.mvp.view.contract.base.BaseView;
import com.example.yangyang.mvpproject.widget.dialog.ProgressDialog;
import com.example.yangyang.mvpproject.widget.placeHolder.PlaceHolderView;
public abstract class BaseActivity extends AppCompatActivity {
private ProgressDialog progressDialog = null;
protected PlaceHolderView mPlaceHolderView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initWindows();
if (initArgs(getIntent().getExtras())) {
setContentView(getContentLayoutId());
initWidget();
initData();
} else {
Toast.makeText(this, "Bundle传值错误", Toast.LENGTH_SHORT).show();
}
}
protected void initWindows() {
}
protected boolean initArgs(Bundle bundle) { // Bundle传值拿参数时可以复写这个函数
return true;
}
protected abstract int getContentLayoutId();
protected void initWidget() {
}
protected void initData() {
}
protected void showProgress(String message){
if (progressDialog == null){
progressDialog = new ProgressDialog(this);
progressDialog.setMessage(message);
progressDialog.show();
}
}
protected void hideProgress(){
if (progressDialog != null){
progressDialog.dismiss();
}
}
protected void setmPlaceHolderView(PlaceHolderView mPlaceHolderView) {
this.mPlaceHolderView = mPlaceHolderView;
}
}
这个我是借鉴了之前的一个BaseActivity搭建,将view 和 data的初始化分开了,同时因为intent中带有bundle,可以复写initArgs将bundle取出,其实在这里是可以实现Baseview的方法,就不用每个界面都重写这两个方法了
重点介绍下PlaceHolderView 是当我们数据返回为空或者网络错误时我们一般都会显示一个界面,这个占位布局的功能就是如此
先贴出PlaceHolderView 代码,他只是一个接口啦
package com.example.yangyang.mvpproject.widget.placeHolder;
import android.support.annotation.StringRes;
public interface PlaceHolderView {
/**
* 没有数据
* 显示空布局,隐藏当前数据布局
*/
void triggerEmpty();
/**
* 网络错误
* 显示一个网络错误的图标
*/
void triggerNetError();
/**
* 加载错误,并显示错误信息
*
* @param strRes 错误信息
*/
void triggerError(@StringRes int strRes);
/**
* 显示正在加载的状态
*/
void triggerLoading();
/**
* 数据加载成功,
* 调用该方法时应该隐藏当前占位布局
*/
void triggerOk();
/**
* 该方法如果传入的isOk为True则为成功状态,
* 此时隐藏布局,反之显示空数据布局
*
* @param isOk 是否加载成功数据
*/
void triggerOkOrEmpty(boolean isOk);
}
这里有注释我就不说了
其实现类是EmptyView
package com.example.yangyang.mvpproject.widget.placeHolder;
import android.content.Context;
import android.opengl.Visibility;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.yangyang.mvpproject.R;
public class EmptyView extends LinearLayout implements PlaceHolderView {
private ImageView mEmptyImg;
private TextView mStatusText;
private int[] mDrawableIds = new int[]{0, 0}; // 设置不同情况下的图片
private String[] mTextI = { "数据为空","网络不太好啊"}; //设置不同情况下的文字
private View[] mBindViews;
public EmptyView(Context context) {
super(context);
init(null, 0);
}
public EmptyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs,0);
}
public EmptyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs,0);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public EmptyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs,0);
}
private void init(AttributeSet attrs, int defStyle) {
inflate(getContext(), R.layout.layout_empty, this);
mEmptyImg = findViewById(R.id.img_empty);
mStatusText = findViewById(R.id.txt_empty);
}
/**
* 将外部布局绑定进来
* @param views
*/
public void bind(View... views) {
this.mBindViews = views;
}
/**
* 隐藏外部布局
* @param visible
*/
private void changeBindViewVisibility(int visible) {
final View[] views = mBindViews;
if (views == null || views.length == 0)
return;
for (View view : views) {
view.setVisibility(visible);
}
}
@Override
public void triggerEmpty() {
mEmptyImg.setImageResource(mDrawableIds[0]);
mStatusText.setText(mTextI[0]);
setVisibility(VISIBLE);
changeBindViewVisibility(GONE);
}
@Override
public void triggerNetError() {
mEmptyImg.setImageResource(mDrawableIds[1]);
mStatusText.setText(mTextI[1]);
setVisibility(VISIBLE);
changeBindViewVisibility(GONE);
}
@Override
public void triggerError(int strRes) {
}
@Override
public void triggerLoading() {
}
@Override
public void triggerOk() {
setVisibility(GONE);
changeBindViewVisibility(VISIBLE);
}
@Override
public void triggerOkOrEmpty(boolean isOk) {
if (isOk) triggerOk();
else triggerEmpty();
}
}
主要是就是bind方法 就是你要讲你所改变的布局给传进来,然后通过changeBindViewVisibility()来将传进来布局设置为可见或者不可见()ememm反正我刚开始看时候没看懂的,后来才知道啥回事,入宫看不懂问我怎么用吧,我会仔细讲解
这个时候,BaseActivity中的PlaceHolderView 就是EmptyView 所以将这个布局写上去,就可以控制可见与不可见了,我觉得超叼,我以前写项目都是在activity里面临时判断,代码贼多,还难改,佩服佩服
这个是BaseFragment
package com.i61.user.teacher.mvp.view.impl.fragment.base;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.i61.user.teacher.mvp.dialog.ProgressDialog;
import com.i61.user.teacher.mvp.view.contract.base.BaseViewInterface;
import com.i61.user.teacher.networkServices.disposable.SubscriptionManager;
import java.util.List;
/**
* 所有fragment继承此fragment(onFragmentResume和onFragmentPause:fragment的可见和不可见,避免了fragment生命周期对不的情况)
*/
public abstract class BaseFragment extends Fragment {
private boolean isLastVisible = false;
private boolean hidden = false;
private boolean isFirst = true;
private boolean isResuming = false;
private boolean isViewDestroyed = false;
private ProgressDialog progressDialog;
protected View parentView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isLastVisible = false;
hidden = false;
isFirst = true;
isViewDestroyed = false;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
parentView = inflater.inflate(getLayoutResId(), container, false);
return parentView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
finishCreateView(savedInstanceState);
}
/**
* 把Fragment里的请求绑到生命周期上
*/
public abstract BaseViewInterface bindToFragmentCycle();
/**
* 添加layout
* @return
*/
public abstract int getLayoutResId();
/**
* view完成了创建
* @param state
*/
public abstract void finishCreateView(Bundle state);
/**
* Fragment 可见时回调
*
* @param isFirst 是否是第一次显示
* @param isViewDestroyed Fragment中的View是否被回收过。
* 存在这种情况:Fragment 的 View 被回收,但是Fragment实例仍在。
*/
protected void onFragmentResume(boolean isFirst, boolean isViewDestroyed) {
}
/**
* Fragment 不可见时回调
*/
protected void onFragmentPause() {
}
/**
* fragment里面显示loading
*/
protected void showProgressDialog(String msg) {
if (progressDialog == null) {
progressDialog = new ProgressDialog(getActivity());
progressDialog.setTextView(msg);
progressDialog.show();
}
}
/**
* fragment隐藏loading
*/
protected void hideProgressDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
}
@Override
public void onResume() {
super.onResume();
isResuming = true;
tryToChangeVisibility(true);
}
@Override
public void onPause() {
super.onPause();
isResuming = false;
tryToChangeVisibility(false);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
setUserVisibleHintClient(isVisibleToUser);
}
private void setUserVisibleHintClient(boolean isVisibleToUser) {
tryToChangeVisibility(isVisibleToUser);
if (isAdded()) {
// 当Fragment不可见时,其子Fragment也是不可见的。因此要通知子Fragment当前可见状态改变了。
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment instanceof BaseFragment) {
((BaseFragment) fragment).setUserVisibleHintClient(isVisibleToUser);
}
}
}
}
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
onHiddenChangedClient(hidden);
}
public void onHiddenChangedClient(boolean hidden) {
this.hidden = hidden;
tryToChangeVisibility(!hidden);
if (isAdded()) {
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment instanceof BaseFragment) {
((BaseFragment) fragment).onHiddenChangedClient(hidden);
}
}
}
}
}
private void tryToChangeVisibility(boolean tryToShow) {
// 上次可见
if (isLastVisible) {
if (tryToShow) {
return;
}
if (!isFragmentVisible()) {
onFragmentPause();
isLastVisible = false;
}
// 上次不可见
} else {
boolean tryToHide = !tryToShow;
if (tryToHide) {
return;
}
if (isFragmentVisible()) {
onFragmentResume(isFirst, isViewDestroyed);
isLastVisible = true;
isFirst = false;
}
}
}
//Fragment是否可见
public boolean isFragmentVisible() {
if (isResuming()
&& getUserVisibleHint()
&& !hidden) {
return true;
}
return false;
}
//Fragment 是否在前台
private boolean isResuming() {
return isResuming;
}
@Override
public void onDestroyView() {
super.onDestroyView();
isViewDestroyed = true;
}
@Override
public void onDestroy() {
super.onDestroy();
if(bindToFragmentCycle() != null){
SubscriptionManager.getInstance().removeViewReqs(bindToFragmentCycle());
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onDetach() {
super.onDetach();
}
}
哈哈我差点把这个遗漏了,主要是我自己也没看,不过很简单的,我先把代码贴出来
其余就直接贴代码了
RecyclerView的封装
对application 的封装
ActivityLifecycle
package com.example.yangyang.mvpproject.app;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class ActivityLifecycle implements Application.ActivityLifecycleCallbacks {
public static final String IS_NOT_ADD_ACTIVITY_LIST = "IS_NOT_ADD_ACTIVITY_LIST";
private ActivityManager activityManager;
public ActivityLifecycle(ActivityManager activityManager) {
this.activityManager = activityManager;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
//如果intent包含了此字段,并且为true说明不加入到list
// 默认为false,如果不需要管理(比如不需要在退出所有activity(killAll)时,退出此activity就在intent加此字段为true)
boolean isNotAdd = false;
if (activity.getIntent() != null)
isNotAdd = activity.getIntent().getBooleanExtra(IS_NOT_ADD_ACTIVITY_LIST, false);
if (!isNotAdd)
activityManager.addActivity(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
activityManager.setCurrentActivity(activity);
}
@Override
public void onActivityPaused(Activity activity) {
if (activityManager.getCurrentActivity() == activity) {
activityManager.setCurrentActivity(null);
}
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
activityManager.removeActivity(activity);
}
}
ActivityManager
package com.example.yangyang.mvpproject.app;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.view.View;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class ActivityManager {
private Application mApplication;
//管理所有activity
public List<Activity> mActivityList;
//当前在前台的activity
private static Activity mCurrentActivity;
private static ActivityManager mInstance;
public static ActivityManager getInstance(Application application) {
if (mInstance == null) {
synchronized (ActivityManager.class) {
if (mInstance == null) {
mInstance = new ActivityManager(application);
}
}
}
return mInstance;
}
private ActivityManager(Application application) {
this.mApplication = application;
}
/**
* 使用snackbar显示内容
*
* @param message
* @param isLong
*/
public void showSnackbar(String message, boolean isLong) {
if (getCurrentActivity() == null) {
return;
}
View view = getCurrentActivity().getWindow().getDecorView().findViewById(android.R.id.content);
}
/**
* 让在前台的activity,打开下一个activity
*
* @param intent
*/
public void startActivity(Intent intent) {
if (getCurrentActivity() == null) {
//如果没有前台的activity就使用new_task模式启动activity
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mApplication.startActivity(intent);
return;
}
getCurrentActivity().startActivity(intent);
}
/**
* 让在前台的activity,打开下一个activity
*
* @param activityClass
*/
public void startActivity(Class activityClass) {
startActivity(new Intent(mApplication, activityClass));
}
/**
* 释放资源
*/
public void release() {
mActivityList.clear();
mActivityList = null;
mCurrentActivity = null;
mApplication = null;
}
/**
* 将在前台的activity保存
*
* @param currentActivity
*/
public void setCurrentActivity(Activity currentActivity) {
this.mCurrentActivity = currentActivity;
}
/**
* 获得当前在前台的activity
*
* @return
*/
public static Activity getCurrentActivity() {
return mCurrentActivity;
}
/**
* 返回一个存储所有未销毁的activity的集合
*
* @return
*/
public List<Activity> getActivityList() {
if (mActivityList == null) {
mActivityList = new LinkedList<>();
}
return mActivityList;
}
/**
* 添加Activity到集合
*/
public void addActivity(Activity activity) {
if (mActivityList == null) {
mActivityList = new LinkedList<>();
}
synchronized (ActivityManager.class) {
if (!mActivityList.contains(activity)) {
mActivityList.add(activity);
}
}
}
/**
* 删除集合里的指定activity
*
* @param activity
*/
public void removeActivity(Activity activity) {
if (mActivityList == null) {
return;
}
synchronized (ActivityManager.class) {
if (mActivityList.contains(activity)) {
mActivityList.remove(activity);
}
}
}
/**
* 删除集合里的指定位置的activity
*
* @param location
*/
public Activity removeActivity(int location) {
if (mActivityList == null) {
return null;
}
synchronized (ActivityManager.class) {
if (location > 0 && location < mActivityList.size()) {
return mActivityList.remove(location);
}
}
return null;
}
/**
* 关闭指定activity
*
* @param activityClass
*/
public void killActivity(Class<?> activityClass) {
if (mActivityList == null) {
return;
}
for (Activity activity : mActivityList) {
if (activity.getClass().equals(activityClass)) {
activity.finish();
}
}
}
/**
* 指定的activity实例是否存活
*
* @param activity
* @return
*/
public boolean activityInstanceIsLive(Activity activity) {
if (mActivityList == null) {
return false;
}
return mActivityList.contains(activity);
}
/**
* 指定的activity class是否存活(一个activity可能有多个实例)
*
* @param activityClass
* @return
*/
public boolean activityClassIsLive(Class<?> activityClass) {
if (mActivityList == null) {
return false;
}
for (Activity activity : mActivityList) {
if (activity.getClass().equals(activityClass)) {
return true;
}
}
return false;
}
/**
* 关闭所有activity
*/
private void killAll() {
Iterator<Activity> iterator = getActivityList().iterator();
while (iterator.hasNext()) {
iterator.next().finish();
iterator.remove();
}
}
/**
* 退出应用程序
*/
public void AppExit() {
try {
killAll();
if (mActivityList != null)
mActivityList = null;
// android.app.ActivityManager activityMgr =
// (android.app.ActivityManager) mApplication.getSystemService(Context.ACTIVITY_SERVICE);
// activityMgr.killBackgroundProcesses(mApplication.getPackageName());
// System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyApp
package com.example.yangyang.mvpproject.app;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.os.Build;
import java.util.LinkedList;
import java.util.List;
public class MyApp extends Application {
/**
* 需要持有context的方法可以传递这个app,避免内存泄漏
*/
public static MyApp app = null;
/**
* Activity管理
*/
private List<Activity> mActivityList = new LinkedList<>();
protected ActivityManager mActivityManager;
protected ActivityLifecycle mActivityLifecycle;
@Override
public void onCreate() {
super.onCreate();
app = this;
mActivityManager = ActivityManager.getInstance(this);
mActivityLifecycle = new ActivityLifecycle(mActivityManager);
registerActivityLifecycleCallback(mActivityLifecycle);
}
public List<Activity> getmActivityList() {
return mActivityList;
}
public void setmActivityList(List<Activity> mActivityList) {
this.mActivityList = mActivityList;
}
/**
* 添加activity
* @param activity
*/
public void addActivity(Activity activity) {
if (mActivityList != null && mActivityList.size() > 0) {
if (!mActivityList.contains(activity)) {
mActivityList.add(activity);
}
} else {
mActivityList.add(activity);
}
}
/**
* 移除activity
*/
public void removeActivity(Activity activity) {
if (mActivityList != null && mActivityList.size() > 0) {
if (mActivityList.contains(activity)) {
mActivityList.remove(activity);
}
}
}
/**
* 遍历mActivityList,结束每一个activity的声明周期
*/
public void finishAllActivityt() {
if (mActivityList != null && mActivityList.size() > 0) {
for (Activity activity : mActivityList) {
activity.finish();
}
}
}
/**
* 完全退出程序
*/
public void appExit() {
finishAllActivityt();
// 正常退出
System.exit(0);
}
/**
* 出现异常杀掉进程
*/
public void appKill() {
finishAllActivityt();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
this.registerActivityLifecycleCallbacks(callbacks);
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void unregisterActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
this.unregisterActivityLifecycleCallbacks(callbacks);
}
@Override
public void onTerminate() {
super.onTerminate();
if (mActivityLifecycle != null) {
unregisterActivityLifecycleCallback(mActivityLifecycle);
}
if (mActivityManager != null) {//释放资源
this.mActivityManager.release();
this.mActivityManager = null;
}
if(app != null){
app = null;
}
}
}
其实还有对RecyclerView的封装,这是我看视频学到的,其实,也不难
package com.example.base.base.recycler;
import android.support.annotation.LayoutRes;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.base.R;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public abstract class RecyclerAdapter<Data>
extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder<Data>>
implements View.OnClickListener, View.OnLongClickListener, AdapterCallback<Data> {
private final List<Data> mDataList;
private AdapterListener<Data> mListener;
/**
* 构造函数模块
*/
public RecyclerAdapter() {
this(null);
}
public RecyclerAdapter(AdapterListener<Data> listener) {
this(new ArrayList<Data>(), listener);
}
public RecyclerAdapter(List<Data> dataList, AdapterListener<Data> listener) {
this.mDataList = dataList;
this.mListener = listener;
}
/**
* 复写默认的布局类型返回
*
* @param position 坐标
* @return 类型,其实复写后返回的都是XML文件的ID
*/
@Override
public int getItemViewType(int position) {
return getItemViewType(position, mDataList.get(position));
}
/**
* 得到布局的类型
*
* @param position 坐标
* @param data 当前的数据
* @return XML文件的ID,用于创建ViewHolder
*/
@LayoutRes
protected abstract int getItemViewType(int position, Data data);
/**
* 创建一个ViewHolder
*
* @param parent RecyclerView
* @param viewType 界面的类型,约定为XML布局的Id
* @return ViewHolder
*/
@Override
public ViewHolder<Data> onCreateViewHolder(ViewGroup parent, int viewType) {
// 得到LayoutInflater用于把XML初始化为View
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
// 把XML id为viewType的文件初始化为一个root View
View root = inflater.inflate(viewType, parent, false);
// 通过子类必须实现的方法,得到一个ViewHolder
ViewHolder<Data> holder = onCreateViewHolder(root, viewType);
// 设置View的Tag为ViewHolder,进行双向绑定
root.setTag(R.id.tag_recycler_holder, holder);
// 设置事件点击
root.setOnClickListener(this);
root.setOnLongClickListener(this);
// 进行界面注解绑定
holder.unbinder = ButterKnife.bind(holder, root);
// 绑定callback
holder.callback = this;
return holder;
}
/**
* 得到一个新的ViewHolder
*
* @param root 根布局
* @param viewType 布局类型,其实就是XML的ID
* @return ViewHolder
*/
protected abstract ViewHolder<Data> onCreateViewHolder(View root, int viewType);
/**
* 绑定数据到一个Holder上
*
* @param holder ViewHolder
* @param position 坐标
*/
@Override
public void onBindViewHolder(ViewHolder<Data> holder, int position) {
// 得到需要绑定的数据
Data data = mDataList.get(position);
// 触发Holder的绑定方法
holder.bind(data);
}
/**
* 得到当前集合的数据量
*/
@Override
public int getItemCount() {
return mDataList.size();
}
/**
* 返回整个集合
*
* @return List<Data>
*/
public List<Data> getItems() {
return mDataList;
}
/**
* 插入一条数据并通知插入
*
* @param data Data
*/
public void add(Data data) {
mDataList.add(data);
notifyItemInserted(mDataList.size() - 1);
}
/**
* 插入一堆数据,并通知这段集合更新
*
* @param dataList Data
*/
public void add(Data... dataList) {
if (dataList != null && dataList.length > 0) {
int startPos = mDataList.size();
Collections.addAll(mDataList, dataList);
notifyItemRangeInserted(startPos, dataList.length);
}
}
/**
* 插入一堆数据,并通知这段集合更新
*
* @param dataList Data
*/
public void add(Collection<Data> dataList) {
if (dataList != null && dataList.size() > 0) {
int startPos = mDataList.size();
mDataList.addAll(dataList);
notifyItemRangeInserted(startPos, dataList.size());
}
}
/**
* 删除操作
*/
public void clear() {
mDataList.clear();
notifyDataSetChanged();
}
/**
* 替换为一个新的集合,其中包括了清空
*
* @param dataList 一个新的集合
*/
public void replace(Collection<Data> dataList) {
mDataList.clear();
if (dataList == null || dataList.size() == 0)
return;
mDataList.addAll(dataList);
notifyDataSetChanged();
}
@Override
public void update(Data data, ViewHolder<Data> holder) {
// 得到当前ViewHolder的坐标
int pos = holder.getAdapterPosition();
if (pos >= 0) {
// 进行数据的移除与更新
mDataList.remove(pos);
mDataList.add(pos, data);
// 通知这个坐标下的数据有更新
notifyItemChanged(pos);
}
}
@Override
public void onClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag(R.id.tag_recycler_holder);
if (this.mListener != null) {
// 得到ViewHolder当前对应的适配器中的坐标
int pos = viewHolder.getAdapterPosition();
// 回掉方法
this.mListener.onItemClick(viewHolder, mDataList.get(pos));
}
}
@Override
public boolean onLongClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag(R.id.tag_recycler_holder);
if (this.mListener != null) {
// 得到ViewHolder当前对应的适配器中的坐标
int pos = viewHolder.getAdapterPosition();
// 回掉方法
this.mListener.onItemLongClick(viewHolder, mDataList.get(pos));
return true;
}
return false;
}
/**
* 设置适配器的监听
*
* @param adapterListener AdapterListener
*/
public void setListener(AdapterListener<Data> adapterListener) {
this.mListener = adapterListener;
}
/**
* 我们的自定义监听器
*
* @param <Data> 范型
*/
public interface AdapterListener<Data> {
// 当Cell点击的时候触发
void onItemClick(RecyclerAdapter.ViewHolder holder, Data data);
// 当Cell长按时触发
void onItemLongClick(RecyclerAdapter.ViewHolder holder, Data data);
}
/**
* 自定义的ViewHolder
*
* @param <Data> 范型类型
*/
public static abstract class ViewHolder<Data> extends RecyclerView.ViewHolder {
private Unbinder unbinder;
private AdapterCallback<Data> callback;
protected Data mData;
public ViewHolder(View itemView) {
super(itemView);
}
/**
* 用于绑定数据的触发
*
* @param data 绑定的数据
*/
void bind(Data data) {
this.mData = data;
onBind(data);
}
/**
* 当触发绑定数据的时候,的回掉;必须复写
*
* @param data 绑定的数据
*/
protected abstract void onBind(Data data);
/**
* Holder自己对自己对应的Data进行更新操作
*
* @param data Data数据
*/
public void updateData(Data data) {
if (this.callback != null) {
this.callback.update(data, this);
}
}
}
}
package com.example.base.base.recycler;
/**
* @author qiujuer Email:qiujuer@live.cn
* @version 1.0.0
*/
public interface AdapterCallback<Data> {
void update(Data data, RecyclerAdapter.ViewHolder<Data> holder);
}
接下来便是我以前没听过的,加入网络返回数据并更改UI时,此时Activity被finish掉了,这时候改UI会让app崩掉,所以要进行截断,这运用了rxjava2的知识
package com.example.yangyang.mvpproject.netService.disposable;
import com.example.yangyang.mvpproject.mvp.view.contract.base.BaseView;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
/**
* @description:订阅关系处理
*/
public class SubscriptionManager {
private static SubscriptionManager mManager;
private CompositeDisposable mDisposables;
/**
* 分view保存请求
*/
private Map<BaseView,List<Disposable>> reqMap;
private SubscriptionManager() {
if (mDisposables == null) {
mDisposables = new CompositeDisposable();
reqMap = new HashMap<>();
}
}
public synchronized void add(BaseView v, Disposable subscription) {
if (subscription == null) return;
mDisposables.add(subscription);
List<Disposable> requestCallBacks = reqMap.get(v);
if(requestCallBacks == null){
requestCallBacks = new LinkedList<>();
}
requestCallBacks.add(subscription);
reqMap.put(v,requestCallBacks);
}
public synchronized void remove(Disposable t) {
if (mDisposables != null) {
mDisposables.remove(t);
}
}
/**
* @param v 当前发起请求的界面
*/
public synchronized void removeViewReqs(BaseView v){
try {
List<Disposable> disposables = reqMap.get(v);
if(disposables != null){
for (Disposable t : disposables){
remove(t);
if(disposables != null){
disposables.remove(t);
}
}
}
}catch (Exception e){
}
}
public void clear() {
if (mDisposables != null) {
mDisposables.clear();
}
}
public static SubscriptionManager getInstance() {
if (mManager == null) {
synchronized (SubscriptionManager.class) {
if (mManager == null) {
mManager = new SubscriptionManager();
}
}
}
return mManager;
}
}
整个框架大致如此,一些具体实现的细节我会分部慢慢解析,对此还会扩展
正所谓 活到老学到死