Android 简单的MVP封装

转载请注明出处:https://blog.csdn.net/a512337862/article/details/85165567

前言

之前写过一个普通的BaseActivity,Fragment封装https://blog.csdn.net/a512337862/article/details/81448736,这次的MVP封装是在上次的基础上进行添加修改的。主要功能如下:

  • Handler的弱引用
  • Toast,Loading加载框的显示(可任意在主/子线程中调用)
  • Fragment 替换
  • activity 跳转
  • 沉浸栏相关
  • MVP相关
  • 其他相关封装

BaseMvpViewImpl

BaseMvpViewImpl是View层需要继承的基类接口,在presenter中通过getView().XXX来调用。这里只封装了Toast,Loading加载框相关的接口。可以根据项目的需求自行添加。

import android.support.annotation.StringRes;

/**
 * Author : BlackHao
 * Time : 2018/12/19 19:11
 * Description : View 层基类
 */
public interface BaseMvpViewImpl {
    /**
     * Toast相关
     */
    void showToast(@StringRes int strId);

    void showToast(String str);

    /**
     * 加载框相关
     */
    void showLoading(@StringRes int strId);

    void showLoading(String str);

    void showLoading();

    void dismissLoading();
}

BaseMvpPresenterImpl

BaseMvpViewImpl是Presenter层需要继承的基类接口,在View层(activity/fragment)中通过getPresenter().XXX来调用。这里只封装了activity/fragment生命周期相关的接口。可以根据项目的需求自行添加。

/**
 * Author : BlackHao
 * Time : 2018/12/19 19:48
 * Description : Presenter 封装
 */
public interface BaseMvpPresenterImpl {

    /**
     * 开始创建 View
     */
    void onViewCreate();

    /**
     * View 创建完成
     */
    void onViewCreated();

    /**
     * Activity / fragment 生命周期
     */
    void onResume();

    void onStart();

    void onPause();

    void onStop();

    void onDestroy();
}

BaseMvpPresenter

BaseMvpPresenter是Presenter的基类,这里主要是对ViewImpl,Context实现了弱引用,并提供获取ViewImpl,Context的方法,避免内存泄漏。

import android.content.Context;

import java.lang.ref.WeakReference;

/**
 * Author : BlackHao
 * Time : 2018/12/20 09:05
 * Description : Presenter 封装
 */
public abstract class BaseMvpPresenter implements BaseMvpPresenterImpl {

    /**
     * 弱引用持有,避免造成内存泄漏
     */
    private WeakReference mView;
    private WeakReference mContext;

    public BaseMvpPresenter(Context context, T mView) {
        this.mView = new WeakReference<>(mView);
        this.mContext = new WeakReference<>(context);
    }


    public T getView() {
        return mView.get();
    }

    public Context getContext() {
        return mContext.get();
    }

    @Override
    public void onViewCreate() {

    }

    @Override
    public void onViewCreated() {

    }

    @Override
    public void onResume() {

    }

    @Override
    public void onStart() {

    }

    @Override
    public void onPause() {

    }

    @Override
    public void onStop() {

    }

    @Override
    public void onDestroy() {

    }

}

BaseMvpActivity/BaseMvpFragment

BaseMvpActivity/BaseMvpFragment 是View的基类,只需重写initPresenter()即可通过getPresenter()来获取PresenterImpl,从而调用对应Presenter中的方法。如果不需要调用,可以直接在initPresenter()中返回null。
因为BaseMvpFragment很多方法的实现都是通过调用BaseMvpActivity中的方法来实现的,所以BaseMvpFragment必须在BaseMvpActivity中调用

BaseMvpActivity

import android.annotation.StringRes;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.IdRes;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.SparseArray;
import android.view.View;
import android.widget.Toast;

import com.balckhao.blackhaoutil.base.LoadingDialog;
import com.balckhao.blackhaoutil.logUtil.LogUtil;

import java.lang.ref.WeakReference;

/**
 * Author : BlackHao
 * Time : 2018/12/20 16:38
 * Description : Base MVP Activity
 */

public abstract class BaseMvpActivity extends AppCompatActivity implements BaseMvpViewImpl {

    //Handler
    public WeakHandler handler;
    //用于保存对应 FrameLayout当前显示的 Fragment
    private SparseArray fragmentArray;
    //LogUtil
    public LogUtil log;
    //加载框
    private LoadingDialog loadingDialog;
    // Presenter
    private T mPresenter;
    //使用状态栏模式
    private int statusMode = -1;
    /**
     * 不使用状态栏
     */
    public static int NO_STATUS = -1;
    /**
     * 沉浸式状态栏
     */
    public static int TRANSLUCENT_STATUS = 1;
    /**
     * 隐藏状态栏
     */
    public static int HIDE_STATUS = 2;
    /**
     * 全屏(隐藏状态栏和导航栏)
     */
    public static int FULL_SCREEN_STATUS = 3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //初始化Log
        log = LogUtil.getInstance();
        //初始化fragmentArray
        fragmentArray = new SparseArray<>();
        //
        loadingDialog = new LoadingDialog();
        //获取presenter
        mPresenter = initPresenter();
        if (mPresenter != null)
            mPresenter.onViewCreate();
        //初始化UI
        initUI();
        //初始化weakHandler
        initHandler();
        //隐藏 ActionBar
        if (getSupportActionBar() != null) {
            getSupportActionBar().hide();
        }
        //更改状态栏模式
        statusMode = getStatusMode();
        if (statusMode == TRANSLUCENT_STATUS) {
            translucentStatus();
        } else if (statusMode == HIDE_STATUS) {
            hideStatusBar();
        }
        //view 初始化完成
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                //
                if (mPresenter != null)
                    mPresenter.onViewCreated();
                //初始化数据
                initData();
                //添加listener
                initListener();
            }
        });
    }

    /**
     * 初始化UI
     */
    protected abstract void initUI();

    /**
     * UI初始化完成,初始化数据
     */
    protected abstract void initData();

    /**
     * UI初始化完成,初始化接口
     */
    protected abstract void initListener();

    /**
     * 子类要处理 handler的消息,重写该方法
     */
    protected abstract void handleMessage(Message msg);

    /**
     * 初始化 Handler
     */
    private void initHandler() {
        handler = new WeakHandler(this);
    }

    /**
     * 初始化 presenter
     */
    protected abstract T initPresenter();

    /**
     * 获取 presenter
     */
    public T getPresenter() {
        return mPresenter;
    }

    /**
     * 获取状态栏模式(默认无状态栏模式,修改状态栏模式只需重写该方法)
     */
    public int getStatusMode() {
        return NO_STATUS;
    }

    /**
     * 显示 Toast(可以在子线程中调用)
     */
    @Override
    public void showToast(final String str) {
        if (!isUIThread()) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    showToast(str);
                }
            });
            return;
        }
        Toast.makeText(BaseMvpActivity.this, str, Toast.LENGTH_SHORT).show();
    }

    /**
     * 显示 Toast(可以在子线程中调用)
     */
    @Override
    public void showToast(@StringRes int strId) {
        showToast(getString(strId));
    }

    /**
     * 加载框相关
     */
    @Override
    public void showLoading(@StringRes int strId) {
        showLoading(getString(strId));
    }


    @Override
    public void showLoading(final String str) {
        if (!isUIThread()) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    showLoading(str);
                }
            });
            return;
        }
        log.e("show : " + str);
        loadingDialog.setLoadingTxt(str);
        loadingDialog.show(getSupportFragmentManager(), "loading");
    }


    @Override
    public void showLoading() {
        showLoading("");
    }


    @Override
    public void dismissLoading() {
        if (!isUIThread()) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    dismissLoading();
                }
            });
            return;
        }
        loadingDialog.dismiss();
    }

    /**
     * 替换 fragment
     *
     * @param frameId      frameLayout id
     * @param showFragment 需要显示的 Fragment
     */
    public void replaceFragment(@IdRes int frameId, Fragment showFragment) {
        Fragment currentFragment = fragmentArray.get(frameId);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        //用于fragment的显示与隐藏
        if (currentFragment != null && currentFragment != showFragment) {
            if (!showFragment.isAdded()) {    // 先判断是否被add过
                transaction.hide(currentFragment).add(frameId, showFragment).commit(); // 隐藏当前的fragment,add下一个到Activity中
            } else {
                transaction.hide(currentFragment).show(showFragment).commit(); // 隐藏当前的fragment,显示下一个
            }
            fragmentArray.put(frameId, showFragment);
        } else if (currentFragment == null) {
            if (!showFragment.isAdded()) {    // 先判断是否被add过
                transaction.add(frameId, showFragment).commit(); // 隐藏当前的fragment,add下一个到Activity中
            } else {
                transaction.show(showFragment).commit(); // 隐藏当前的fragment,显示下一个
            }
            fragmentArray.put(frameId, showFragment);
        }
    }

    /**
     * activity 跳转
     *
     * @param target      需要跳转的 Activity
     * @param bundle      bundle
     * @param isCloseSelf 是否关闭当前的 activity
     */
    public void openActivity(Class target, Bundle bundle, boolean isCloseSelf) {
        Intent intent = new Intent(this, target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
        if (isCloseSelf) {
            finish();
        }
    }

    /**
     * activity 跳转(不需要传值)
     *
     * @param target 需要跳转的Activity
     */
    public void openActivity(Class target) {
        openActivity(target, null, false);
    }

    /**
     * activity 跳转
     *
     * @param target      需要跳转的 Activity
     * @param bundle      bundle
     * @param requestCode requestCode
     */
    public void openActivityForResult(Class target, Bundle bundle, int requestCode) {
        Intent intent = new Intent(this, target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    /**
     * 生命周期相关
     */
    @Override
    protected void onResume() {
        super.onResume();
        if (mPresenter != null)
            mPresenter.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mPresenter != null)
            mPresenter.onPause();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mPresenter != null)
            mPresenter.onStart();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mPresenter != null)
            mPresenter.onDestroy();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mPresenter != null)
            mPresenter.onStop();
    }

    /**
     * 判断当前线程是否在主线程
     */
    public boolean isUIThread() {
        return Thread.currentThread().getId() == Looper.getMainLooper().getThread().getId();
    }

    /**
     * 沉浸式状态栏
     */
    public void translucentStatus() {
        //5.0及以上系统才支持
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
    }

    /**
     * 隐藏状态栏
     */
    public void hideStatusBar() {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(option);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        //Android 4.4及以上系统才支持
        if (statusMode == FULL_SCREEN_STATUS && hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        }
    }

    /**
     * 弱引用 handler
     */
    public static class WeakHandler extends Handler {
        WeakReference weakReference;

        WeakHandler(BaseMvpActivity activity) {
            this.weakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            BaseMvpActivity activity = (BaseMvpActivity) weakReference.get();
            switch (msg.what) {
                default:
                    if (activity != null) {
                        activity.handleMessage(msg);
                    }
                    break;
            }
        }
    }

}

BaseMvpFragment

import android.annotation.StringRes;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.balckhao.blackhaoutil.logUtil.LogUtil;

/**
 * Author : BlackHao
 * Time : 2018/12/20 16:38
 * Description : Base MVP Fragment (必须在 BaseMvpActivity 中调用)
 */

public abstract class BaseMvpFragment extends Fragment implements BaseMvpViewImpl {

    //用于保存对应 FrameLayout当前显示的 Fragment
    private SparseArray fragmentArray;
    //LogUtil
    public LogUtil log;
    // Presenter
    private T mPresenter;
    //Activity
    private BaseMvpActivity activity;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activity = (BaseMvpActivity) getActivity();
        mPresenter = initPresenter();
        //
        fragmentArray = new SparseArray<>();
        log = activity.log;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(initLayoutId(), container, false);
        initUI(view);
        //
        if (mPresenter != null)
            mPresenter.onViewCreate();
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initData();
        initListener();
        if (mPresenter != null)
            mPresenter.onViewCreated();
    }

    /**
     * 初始化UI
     */
    protected abstract int initLayoutId();

    /**
     * 初始化UI
     */
    protected abstract void initUI(View view);

    /**
     * UI初始化完成,初始化数据
     */
    protected abstract void initData();

    /**
     * UI初始化完成,初始化接口
     */
    protected abstract void initListener();

    /**
     * 初始化 presenter
     */
    protected abstract T initPresenter();

    /**
     * 获取 presenter
     */
    public T getPresenter() {
        return mPresenter;
    }

    /**
     * 显示 Toast(可以在子线程中调用)
     */
    @Override
    public void showToast(final String str) {
        activity.showToast(str);
    }

    /**
     * 显示 Toast(可以在子线程中调用)
     */
    @Override
    public void showToast(@StringRes int strId) {
        showToast(getString(strId));
    }

    /**
     * 加载框相关
     */
    @Override
    public void showLoading(@StringRes int strId) {
        showLoading(getString(strId));
    }


    @Override
    public void showLoading(String str) {
        activity.showLoading(str);
    }


    @Override
    public void showLoading() {
        activity.showLoading();
    }


    @Override
    public void dismissLoading() {
        activity.dismissLoading();
    }

    /**
     * 替换 fragment
     *
     * @param frameId      frameLayout id
     * @param showFragment 需要显示的 Fragment
     */
    public void replaceFragment(@IdRes int frameId, Fragment showFragment) {
        Fragment currentFragment = fragmentArray.get(frameId);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        //用于fragment的显示与隐藏
        if (currentFragment != null && currentFragment != showFragment) {
            if (!showFragment.isAdded()) {    // 先判断是否被add过
                transaction.hide(currentFragment).add(frameId, showFragment).commit(); // 隐藏当前的fragment,add下一个到Activity中
            } else {
                transaction.hide(currentFragment).show(showFragment).commit(); // 隐藏当前的fragment,显示下一个
            }
            fragmentArray.put(frameId, showFragment);
        } else if (currentFragment == null) {
            if (!showFragment.isAdded()) {    // 先判断是否被add过
                transaction.add(frameId, showFragment).commit(); // 隐藏当前的fragment,add下一个到Activity中
            } else {
                transaction.show(showFragment).commit(); // 隐藏当前的fragment,显示下一个
            }
            fragmentArray.put(frameId, showFragment);
        }
    }

    /**
     * activity 跳转
     *
     * @param target      需要跳转的 Activity
     * @param bundle      bundle
     * @param isCloseSelf 是否关闭当前的 activity
     */
    public void openActivity(Class target, Bundle bundle, boolean isCloseSelf) {
        Intent intent = new Intent(getContext(), target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
        if (isCloseSelf) {
            activity.finish();
        }
    }

    /**
     * activity 跳转(不需要传值)
     *
     * @param target 需要跳转的Activity
     */
    public void openActivity(Class target) {
        openActivity(target, null, false);
    }

    /**
     * activity 跳转
     *
     * @param target      需要跳转的 Activity
     * @param bundle      bundle
     * @param requestCode requestCode
     */
    public void openActivityForResult(Class target, Bundle bundle, int requestCode) {
        Intent intent = new Intent(getContext(), target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    /**
     * 生命周期相关
     */
    @Override
    public void onResume() {
        super.onResume();
        if (mPresenter != null)
            mPresenter.onResume();
    }


    @Override
    public void onPause() {
        super.onPause();
        if (mPresenter != null)
            mPresenter.onPause();
    }

    @Override
    public void onStart() {
        super.onStart();
        if (mPresenter != null)
            mPresenter.onStart();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mPresenter != null)
            mPresenter.onDestroy();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mPresenter != null)
            mPresenter.onStop();
    }

}

结语

  • 源码以及测试demo下载地址:https://github.com/LuoChen-Hao/BlackHaoUtil
  • 有任何问题请留言。

你可能感兴趣的:(android,工具类)