MVP简单抽取+loading动画

BaseApp

import android.app.Application;
import android.content.res.Resources;
import android.support.v7.app.AppCompatDelegate;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;

public class BaseApp extends Application {
    private static BaseApp sBaseApp;
    //默认不是夜间模式
    public static int mMode = AppCompatDelegate.MODE_NIGHT_NO;
    public static int mWidthPixels;
    public static int mHeightPixels;

    @Override
    public void onCreate() {
        super.onCreate();
        sBaseApp = this;
        getScreenWH();
    }

    //计算屏幕宽高
    private void getScreenWH() {
        WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
        Display defaultDisplay = manager.getDefaultDisplay();
        DisplayMetrics metrics = new DisplayMetrics();
        defaultDisplay.getMetrics(metrics);
        mWidthPixels = metrics.widthPixels;
        mHeightPixels = metrics.heightPixels;
    }

    public static BaseApp getInstance(){
        return sBaseApp;
    }

    public static Resources getRes() {
        return sBaseApp.getResources();
    }
}

BaseActivity

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import butterknife.ButterKnife;

/**
 *         MVP
 *         V: 视图展示+用户交互
 *         P: V层和M层的桥梁+业务逻辑
 *         M: 负责数据处理:网络/文件/数据库...耗时操作
 */

public abstract class BaseActivity<V extends BaseView,P extends BasePresenter> extends AppCompatActivity{

    protected P basePresenter;
    private LoadingDialog mLoadingDialog;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(initLayoutId());
        ButterKnife.bind(this);
        basePresenter = initPresenter();
        if (basePresenter!=null){
            //可以强转,但是不对,但是这个基类的子类肯定会实现BaseView或者他的子类
            //mPresenter.bind((BaseMvpView) this);
            basePresenter.bind((V) this);
        }
        initView();
        initListener();
        initData();
    }

    protected abstract P initPresenter();

    protected void initView() {

    }

    protected void initListener() {

    }

    protected void initData() {

    }

    protected abstract int initLayoutId();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        basePresenter.onDestory();
        basePresenter = null;
    }

    @Override
    public void showLoading() {
        if (mLoadingDialog == null){
            mLoadingDialog = new LoadingDialog(this);
        }
        mLoadingDialog.show();
    }

    @Override
    public void hideLoading() {
        if (mLoadingDialog != null && mLoadingDialog.isShowing()){
            mLoadingDialog.dismiss();
        }
    }
}

LoadingDialog(有需要时用)

用来显示请求网络数据之前的加载动画

在res文件夹下的drawable文件里创建loading_img.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_loading"
    android:pivotX="50%"
    android:pivotY="50%" />
在layout文件夹里创建loading_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:src="@drawable/loading_img">

</ImageView>
在values文件夹里的styles.xml文件里
<style name="LoadingTheme" parent="Theme.AppCompat.Dialog">
        <!--dialog背景设置为透明-->
        <item name="android:windowBackground">@color/transparent</item>
        <!--去掉背景半透明效果-->
        <item name="android:backgroundDimEnabled">false</item>
    </style>
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.example.lenovo.everywheretravel.R;

public class LoadingDialog extends Dialog{
    public LoadingDialog(@NonNull Context context) {
        super(context,R.style.LoadingTheme);
    }

    public LoadingDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
    }

    protected LoadingDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loading_dialog);
    }
}
用法

因为是在BaseActivity中写的显示动画的方法,所以要调用这个方法的界面必须是继承自BaseActivity,然后直接在监听里调用showLoading()就可以了

BasePresenter

public abstract class BasePresenter<V extends BaseView> {
    protected V view;

    protected ArrayList<BaseModel> mModels = new ArrayList<>();

    public void bind(V view) {
        this.view=view;
    }

    public BasePresenter() {
        initModel();
    }

    protected abstract void initModel();

    public void onDestory() {
        //打断P层和V层的联系,
        view = null;
        //掐断网络请求
        if (mModels.size()>0){
            for (BaseModel model :mModels) {
                model.onDestory();
            }
            mModels.clear();
        }
    }

}

BaseView

public interface BaseView {
    //显示加载loading的方法
    void showLoading();
    //隐藏加载loading的方法
    void hideLoading();
}

BaseModel

public class BaseModel {
    private CompositeDisposable mCompositeDisposable;

    public void onDestory() {
        //切换所有的Disposable对象
        if (mCompositeDisposable!=null){
            mCompositeDisposable.clear();
        }
    }

    public void addDisposable(Disposable d){
        if (mCompositeDisposable == null){
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(d);
    }
}

BaseFragment

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 butterknife.ButterKnife;
import butterknife.Unbinder;

public abstract class BaseFragment<V extends BaseView,P extends BasePresenter> extends Fragment {

    private Unbinder unbinder;
    protected P basePresenter;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(initLayoutId(), null);

        unbinder = ButterKnife.bind(this, view);
        basePresenter = initPresenter();
        if (basePresenter!=null){
            basePresenter.bind((V) this);
        }
        initView();
        initListener();
        initData();

        return view;
    }

    protected void initView() {

    }

    protected void initListener() {

    }

    protected void initData() {

    }

    protected abstract P initPresenter();

    protected abstract int initLayoutId();

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
        basePresenter.onDestory();
        basePresenter = null;
    }
}

res文件夹下的values文件夹里的strings.xml文件里

<resources>
    // app_name 项目生成时自带的,只需要复制下面的就行
    //<string name="app_name">EveryWhereTravel</string>
    <string name="unknow_error">未知错误</string>
    <string name="conn_error">连接失败</string>
    <string name="conn_timeout">连接超时</string>
    <string name="net_error">网络错误</string>
    <string name="parse_error">解析异常</string>
    <string name="net_unused">当前网络不可用</string>
</resources>

BaseObserver

SystemUtil和ToastUtil在工具类里

import android.net.ParseException;

import com.example.lenovo.everywheretravel.utils.Logger;
import com.example.lenovo.everywheretravel.utils.SystemUtil;
import com.example.lenovo.everywheretravel.utils.ToastUtil;
import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.HttpException;
public abstract class BaseObserver<T> implements Observer<T> {
    private final String TAG = getClass().getName();
    /**
     * 解析数据失败
     */
    public static final int PARSE_ERROR = 1001;
    /**
     * 网络问题
     */
    public static final int BAD_NETWORK = 1002;
    /**
     * 连接错误
     */
    public static final int CONNECT_ERROR = 1003;
    /**
     * 连接超时
     */
    public static final int CONNECT_TIMEOUT = 1004;

    @Override
    public void onError(Throwable e) {
        Logger.logD(TAG, "error: "+e.toString());
        if (e instanceof HttpException) {
            //   HTTP错误
            onException(BAD_NETWORK);
        } else if (e instanceof ConnectException
                || e instanceof UnknownHostException) {
            //   连接错误
            onException(CONNECT_ERROR);
        } else if (e instanceof InterruptedIOException) {
            //  连接超时
            onException(CONNECT_TIMEOUT);
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            //  解析错误
            onException(PARSE_ERROR);
        } else {
            if (e != null) {
                error(e.toString());
            } else {
                error(BaseApp.getRes().getString(R.string.unknow_error));
            }
        }
    }

    private void onException(int unknownError) {
        switch (unknownError) {
            case CONNECT_ERROR:
                error(BaseApp.getRes().getString(R.string.conn_error));
                break;

            case CONNECT_TIMEOUT:
                error(BaseApp.getRes().getString(R.string.conn_timeout));
                break;

            case BAD_NETWORK:
                error(BaseApp.getRes().getString(R.string.net_error));
                break;

            case PARSE_ERROR:
                error(BaseApp.getRes().getString(R.string.parse_error));
                break;

            default:
                break;
        }
    }

    public abstract void error(String msg);

    @Override
    public void onComplete() {
        Logger.logD(TAG, "onComplete: ");
    }

    @Override
    public void onSubscribe(Disposable d) {
        if (!SystemUtil.isNetworkConnected()){
            ToastUtil.showShort(BaseApp.getRes().getString(R.string.net_unused));
            return;
        }
        subscribe(d);
    }

    protected abstract void subscribe(Disposable d);

}

Logger

public class Logger {
    public static void logD(String tag,String msg){
        if (Constants.isDebug){
            Log.d(tag, "logD: "+msg);
        }
    }
}

CallBack

public interface CallBack<K> {
    void onSuccess(K k);
    void onFail(String string);
}

用法

DailyNewsM

public class DailyNewsM extends BaseModel {
    public void getData(final CallBack<DailyNewsBean> callBack) {
        ZhihuService apiserver = HttpUtils.getInstance().getApiserver(ZhihuService.sBaseUrl, ZhihuService.class);
        Observable<DailyNewsBean> lastDailyNews = apiserver.getLastDailyNews();
        lastDailyNews.compose(RxUtils.<DailyNewsBean>rxObserableSchedulerHelper())
                .subscribe(new BaseObserver<DailyNewsBean>() {

                    @Override
                    public void onNext(DailyNewsBean dailyNewsBean) {
                        callBack.onSuccess(dailyNewsBean);
                    }

                    @Override
                    public void error(String msg) {

                    }

                    @Override
                    protected void subscribe(Disposable d) {
                        addDisposable(d);
                    }
                });
    }
}

DailyNewsP

public class DailyNewsP extends BasePresenter<DailyNewsV> {

    private DailyNewsM mDailyNewsM;

    @Override
    protected void initModel() {
        mDailyNewsM = new DailyNewsM();
        mModels.add(mDailyNewsM);
    }

    public void getData() {
        mDailyNewsM.getData(new ResultCallBack<DailyNewsBean>() {
            @Override
            public void onSuccess(DailyNewsBean bean) {
                if (bean != null){
                    if (view != null){
                        view.setData(bean);
                    }
                }
            }

            @Override
            public void onFail(String msg) {

            }
        });
    }
}

DailyNewsV

public interface DailyNewsV extends BaseMvpView {
    void setData(DailyNewsBean bean);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容