APP架构和mvp + retrofit + rxjava的设计

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;
    }

}

整个框架大致如此,一些具体实现的细节我会分部慢慢解析,对此还会扩展

正所谓 活到老学到死

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容