1. 程式人生 > >Mvp實戰心得(二)---Base基類的封裝

Mvp實戰心得(二)---Base基類的封裝

基類:

在開發中有著很重要的地位,基類設計封裝的好,不管是對app的效能,還是對開發的效率都有著很重要的作用

基類可以簡單幾個字概況,一個良好的父類.

結構:

不管你的app是多個acitivity,還是1個activity+n個fragment,還是多個acitivity多個fragment.

始終都是用的acitivity和fragment.

根據專案的不同,基類不可能完全相同,但很多還是可以通用的.

抽取:

既然是mvp,那麼不管是acitivity還是fragment.都歸於v 既然是v,那麼就應該有相對應的presenter,view 那麼基類應該有: BaseActivityView BaseFragmentView BaseView BasePresenter

具體程式碼:

BaseActivity

public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseActivityView {

    protected T mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //建立Presenter
        mPresenter = initPresenter();
        //類似fragment的繫結.拿到引用
        mPresenter.onAttch(this);
        //初始化acitivity,
        onCreateActivity(savedInstanceState);
        //初始化Presenter
        mPresenter.onCreate();
    }


    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mPresenter.onSaveInstanceState(outState);
    }

    @Override
    protected void onDestroy() {
        mPresenter.onDestroy(); 
        mPresenter.onDetach();
        super.onDestroy();
    }

    @Override
    public BaseActivity getActivity() {
        return this;
    }

    /**
     * 建立prensenter
     * @return <T extends BasePresenter> 必須是BasePresenter的子類
     */
    protected abstract T initPresenter();

    /**
     * 子類必須實現,並初始化Activity,比如setContentView()
     */
    protected abstract void onCreateActivity(Bundle savedInstanceState);
    @Override
    public void isNightMode(boolean isNight) {

    }
}

BaseFragment

稍微複雜一點.

public abstract class BaseFragment<T extends BasePresenter> extends Fragment implements BaseFragmentView {
    protected T mPresenter;
    protected Context mContext;//activity的上下文物件
    protected Bundle mBundle;

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mBundle != null) {
            outState.putBundle("bundle", mBundle);
        }
    }
    /**
     * 繫結activity
     *
     * @param context
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    /**
     * 執行在onAttach之後
     * 可以接受別人傳遞過來的引數,例項化物件.
     *
     * @param savedInstanceState
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //獲取bundle,並儲存起來
        if (savedInstanceState != null) {
            mBundle = savedInstanceState.getBundle("bundle");
        } else {
            mBundle = getArguments() == null ? new Bundle() : getArguments();
        }
        //建立presenter
        mPresenter = initPresenter();
    }

    /**
     * 執行在onCreate之後
     * 生成view檢視
     */
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return initView(inflater, container, savedInstanceState);
    }

    /**
     * 執行在onCreateView之後
     * 載入資料
     */
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //由於fragment生命週期比較複雜,所以Presenter在onCreateView建立檢視之後再進行繫結,不然會報空指標異常
        mPresenter.onAttch(this);
        mPresenter.onCreate();
    }

    @Override
    public void onDestroyView() {
        mPresenter.onDestroy();
        super.onDestroyView();
    }
    @Override
    public void onDetach() {
        mPresenter.onDetach();
        super.onDestroyView();
    }
    /**
     * 跳轉fragment
     *
     * @param tofragment
     */
    @Override
    public void startFragment(Fragment tofragment) {
        startFragment(tofragment, null);
    }

    /**
     * @param tofragment 跳轉的fragment
     * @param tag        fragment的標籤
     */
    @Override
    public void startFragment(Fragment tofragment, String tag) {
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.hide(this).add(android.R.id.content, tofragment, tag);
        fragmentTransaction.addToBackStack(tag);
        fragmentTransaction.commitAllowingStateLoss();
    }

    /**
     * 類似Activity的OnBackgress
     * fragment進行回退
     */
    public void onBack() {
        getFragmentManager().popBackStack();
    }

    /**
     * 初始化Fragment應有的檢視
     *
     * @return
     */
    public abstract View initView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);

    /**
     * 建立prensenter
     *
     * @return <T extends BasePresenter> 必須是BasePresenter的子類
     */
    public abstract T initPresenter();

    @Override
    public Context getContext() {
        return mContext;
    }

    @Override
    public Bundle getBundle() {
        return mBundle;
    }

    @Override
    public BaseFragment getFragment() {
        return this;
    }

}

再看看BaseView

public interface BaseView {
    /**
     * 切換夜間模式
     * @param isNight 是否切換為夜間模式
     */
    void isNightMode(boolean isNight);
}

BaseView得想好做什麼事,必須是你的專案裡所有view都有的共性

不僅是acitivity和fragment,還有控制元件

-----------------------------------------------------------------------------------------------------

關鍵的BasePresenter來了

/**
 * @author jlanglang  2016/11/11 15:10
 */
public abstract class BasePresenter<T extends BaseView> {
   protected T mView;

    /**
     * 繫結View
     */
    public void onAttch(T view) {
        this.mView = view;

    }
    /**
     * 做初始化的操作,需要在V的檢視初始化完成之後才能呼叫
     * presenter進行初始化.
     */
    public abstract void onCreate();
    /** 
    * 在這裡結束非同步操作
    */
    public void onDestroy(){

    }
    /**
     * 在V銷燬的時候呼叫,解除繫結
    */
    public void onDetach() {  
       mView = null;
    }
    /**
    * 容易被回收掉時儲存資料
    */
    public abstract void onSaveInstanceState(Bundle outState);
}

看看Acitivity的使用:

//建立的時候寫好泛型實現好抽象方法就行,多麼簡單.
public class MainActivity extends BaseActivity<MainActivityPresenterImpl> implements MainActivityContract.View {
    @Override
    protected MainActivityPresenterImpl initPresenter() {
        return new MainActivityPresenterImpl();
    }

    @Override
    protected void onCreateActivity(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
    }
}

最後是對應的MainActivityPresenterImpl以及MainActivityContract

public class MainActivityPresenterImpl extends BasePresenter<MainActivityContract.View>
 implements MainActivityContract.Presenter {

    @Override
    public void onCreate() {

    }
    @Override
    public void onSaveInstanceState(Bundle outState) {

    }
}
public class MainActivityContract {
    public interface View extends BaseActivityView {
    }

    public interface Presenter{
    }

    public interface Model {
    }

}

總結:

對於BasePresenter一開始我是寫成介面形式的,
後來使用過程中,發現很麻煩,每次繫結View,釋放View都需要重複造輪子.
仔細想想,抽象類更合適,
每個Presenter繼承BasePresenter,實現Contract中的介面為其補充

最後會發現,view和presenter的結構一樣.基類作為複用,介面作為補充.