MVP实战心得(四)---封装优化,拆分Toolbar与ContentView

转载请标明出处:http://www.jianshu.com/p/6b4d764fbb24
本文出自:Jlanglang

前言:

最近发现之前封装的结构,如果作为一个module依赖来开发时
就不是很好用了.只能慢慢改了.

之前不好的地方:

1.Toolbar与ContentView写死在layout,如想要封装loadingView(根据请求状态,显示不同页面),非常麻烦.
2.Toolbar复用是通过include,改动即需要修改layout,也需要修改代码.
3.Presenter不能很好的控制Toolbar.

传送门:MVP实战心得(三)---封装Retrofit2.0+RxAndroid+RxBus

思路:

1.参考源码非NoactionBar主题,Toolbar应该与ContentView分开。
2.参考源码,base_layout的结构可以是LinearLayout里面一个ViewStub(生成toolbar),一个Framlayout(ContentVIew).
3.一个快速开发框架,应该有默认的模板,默认的样式。
4.Toolbar属于View范围,初始化应该在View里面,而不是在Presenter
5.参考AppCompatDelegate实现,提供多种默认的layout,根据layout生成不同的Toolbar。
6.继承BaseActivity,可以通过复写方法,控制是否需要Toolbar,以及自定义Toolbar。
7.ContentView应该使用Framlayout,可以被自由改造,比如:loadingView。。
8,参考AppCompatDelegate,具体实现使用ToolbarHelper的实现类,来代理创建设置Toolbar....BaseActivity不需要去关心这个过程.

来张丑丑的图:


m.png

新增的类:

UIView:

界面View,尽量让Frgament与Activity之间的切换,变的方便.只需改动极少的代码就能进行切换
Presenter,可以通过ToolbarHelper,控制Toolbar进行一些通用的设置.

ToolbarHelper

包含一些通用方法,如:getToolbar,setTitle,通过静态方法Create()传入不同的toolbarLayout的id,返回不同的实现类.

DefuatlToolbarHelperImplV1

默认的Toolbar实现.继承BaseToolBarHelperImpl

BaseToolBarHelperImpl

继承ToolbarHelper,否则创建toolbar,如果使用默认布局,则通过ViewStub
创建,如果使用自定义布局,则直接findview获取toolbar.

具体代码:

UIView:

 package com.baozi.mvpdemo.ui.view;

import android.app.Activity;
import android.content.res.Resources;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.view.View;

/**
 * Created by baozi on 2017/2/20.
 * 用户页面,操作页面,对应Activity,frgament...
 */

public interface UIView extends BaseView {
    /**
     * id查找控件
     * 省去findviewById的强转操作
     *
     * @param viewId 控件id
     * @param <V>    控件类型
     * @return V extends View
     */
    <V extends View> V findView(int viewId);

    /**
     * res资源获取
     *
     * @return
     */
    Resources getResources();

    /**
     * 回退
     */
    void onBack();

    /**
     * 是否自定义布局
     *
     * @return
     */
    boolean isCustomLayout();

    /**
     * 是否使用MaterialDesign风格
     *
     * @return
     */
    boolean isMaterialDesign();

    /**
     * MaterialDesign风格,普通风格之间转换
     *
     * @param isMaterialDesign
     */
    void setMaterialDesignEnabled(boolean isMaterialDesign);

    /**
     * 获取Acitivity
     *
     * @return
     */
    Activity getActivity();

    /**
     * Frgament跳转.
     *
     * @param tofragment
     */
    void startFragment(Fragment tofragment);

    /**
     * Frgament跳转.
     *
     * @param tofragment
     */
    void startFragment(Fragment tofragment, String tag);

    /**
     * 获得getSupportActionBar
     *
     * @return
     */
    ActionBar getSupportActionBar();

    /**
     * 设置getSupportActionBar
     *
     * @param toolbar
     * @return
     */
    void setSupportActionBar(Toolbar toolbar);
    /**
     * 获得ToolbarHelper,Presenter可以通过ToolbarHelper的来控制toolbar
     */
     ToolbarHelper getToolbarHelper();
}  


ToolbarHelper

package com.baozi.mvpdemo.helper;

import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v7.widget.Toolbar;
import android.view.View;

import com.baozi.mvpdemo.R;
import com.baozi.mvpdemo.ui.view.UIView;

/**
 * @author jlanglang  2017/2/21 16:31
 * @版本 2.0
 * @Change
 */
public abstract class ToolbarHelper {
    public static final int DEFUATL_BASE_TOOLBAR_V1 = R.layout.base_toolbar;

    public ToolbarHelper() {

    } 
   /**
     * 创建具体的ToolbarHelper
     *
     * @param uiView        可以通过uiView,设置acitivity,fragment
     * @param toolbarLayout toolbarLayout的id
     * @return ToolbarHelper的具体实现
     */
    public static ToolbarHelper Create(@NonNull UIView uiView, @LayoutRes int toolbarLayout) {
        if (toolbarLayout == DEFUATL_BASE_TOOLBAR_V1) {
            return new DefuatlToolbarHelperImplV1(uiView, toolbarLayout);
        } else {
            return new BaseToolBarHelperImpl(uiView, toolbarLayout);
        }
    }
   /**
     * 初始化Toolbar,对toolbar进行一些设置
     */
    public abstract void initToolbar();
  /**
     * 获取创建的toolbar.
     * @return
     */
    public abstract Toolbar getToolbar();

    /**
     * 设置显示MaterialDesign风格,
     * @param isMaterialDesign 设置是否显示
     */
    public abstract void setMaterialDesignEnabled(boolean isMaterialDesign);

    /**
     * 设置title
     *
     * @param str
     */

    public abstract void setTitle(@NonNull String str);

    public abstract void setTitle(@StringRes int str);

    /**
     * 设置左边
     *
     * @param strId
     */
    public abstract void setLeftText(@StringRes int strId, View.OnClickListener clickListener);

    public abstract void setLeftText(@NonNull String str, View.OnClickListener clickListener);

    public abstract void setLeftButton(Drawable drawable, View.OnClickListener clickListener);

    public abstract void setLeftButton(@DrawableRes int drawableId, View.OnClickListener clickListener);


    /**
     * 设置右边
     *
     * @param str
     */
    public abstract void setRightText(@NonNull String str, View.OnClickListener clickListener);

    public abstract void setRightText(@StringRes int strId, View.OnClickListener clickListener);

    public abstract void setRightButton(@NonNull Drawable drawable, View.OnClickListener clickListener);

    public abstract void setRightButton(@DrawableRes int drawableId, View.OnClickListener clickListener);
}

BaseToolBarHelperImpl

package com.baozi.mvpdemo.helper;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewStub;

import com.baozi.mvpdemo.R;
import com.baozi.mvpdemo.ui.view.UIView;

/**
 * @author jlanglang  2017/2/22 16:58
 * @版本 2.0
 * @Change
 */
public class BaseToolBarHelperImpl extends ToolbarHelper {
    protected int mToolbarLayout;
    protected Toolbar mToolbar;
    protected UIView mUIView;
    protected Context mContext;
    protected boolean isMaterialDesign;

    public BaseToolBarHelperImpl(@NonNull UIView uiView, int toolbarLayout) {
        this.mUIView = uiView;
        this.mContext = uiView.getContext();
        this.mToolbarLayout = toolbarLayout;
        ViewStub vs_toolbar = uiView.findView(R.id.vs_toolbar);
        if (vs_toolbar != null) {
            vs_toolbar.setLayoutResource(mToolbarLayout);
            mToolbar = (Toolbar) vs_toolbar.inflate();
        } else {
            mToolbar = uiView.findView(toolbarLayout);
        }
        initToolbar();
    }

    @Override
    public void initToolbar() {

    }

    @Override
    public Toolbar getToolbar() {
        return mToolbar;
    }

    @Override
    public void setMaterialDesignEnabled(boolean isMaterialDesign) {
        this.isMaterialDesign = isMaterialDesign;
 
    }

    @Override
    public void setTitle(@NonNull String str) {

    }

    @Override
    public void setTitle(@StringRes int str) {

    }

    @Override
    public void setLeftText(@StringRes int strId, View.OnClickListener clickListener) {

    }

    @Override
    public void setLeftText(@NonNull String str, View.OnClickListener clickListener) {

    }

    @Override
    public void setLeftButton(Drawable drawable, View.OnClickListener clickListener) {

    }

    @Override
    public void setLeftButton(@DrawableRes int drawableId, View.OnClickListener clickListener) {

    }

    @Override
    public void setRightText(@NonNull String str, View.OnClickListener clickListener) {

    }

    @Override
    public void setRightText(@StringRes int strId, View.OnClickListener clickListener) {

    }

    @Override
    public void setRightButton(@NonNull Drawable drawable, View.OnClickListener clickListener) {

    }

    @Override
    public void setRightButton(@DrawableRes int drawableId, View.OnClickListener clickListener) {

    }


}

DefuatlToolbarHelperImplV1

package com.baozi.mvpdemo.helper;

import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;

import com.baozi.mvpdemo.R;
import com.baozi.mvpdemo.ui.view.UIView;

/**
 * @author jlanglang  2017/2/21 16:44
 * @版本 2.0
 * @Change
 */

public class DefuatlToolbarHelperImplV1 extends BaseToolBarHelperImpl {
    private TextView mLeftText;
    private TextView mRightText;
    private ImageButton mLeftButton;
    private ImageButton mRightButton;
    private TextView mTitle;

    public DefuatlToolbarHelperImplV1(UIView uiView, @LayoutRes int toolbar) {
        super(uiView, toolbar);
    }

    @Override
    public void initToolbar() {
        mLeftText = (TextView) mToolbar.findViewById(R.id.tv_left);
        mRightText = (TextView) mToolbar.findViewById(R.id.tv_right);
        mLeftButton = (ImageButton) mToolbar.findViewById(R.id.ib_left);
        mRightButton = (ImageButton) mToolbar.findViewById(R.id.ib_right);
        mTitle = (TextView) mToolbar.findViewById(R.id.tv_title);
        setLeftButton(R.drawable.back, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUIView.onBack();
            }
        });

    }

    /**
     * 应该保证在调用Activity.setSupportActionBar()之后使用.
     *
     * @param isMaterialDesign
     */
    @Override
    public void setMaterialDesignEnabled(boolean isMaterialDesign) {
        super.setMaterialDesignEnabled(isMaterialDesign);
        ActionBar supportActionBar = mUIView.getSupportActionBar();
        if (supportActionBar == null) {
            return;
        }
        setTitle(mTitle.getText().toString());
        setLeftButton(mLeftButton.getDrawable(), new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUIView.onBack();
            }
        });
    }

    @Override
    public void setTitle(@NonNull String title) {
        if (isMaterialDesign) {
            mUIView.getSupportActionBar().setTitle(title);
        } else {
            mTitle.setText(title);
        }
    }

    @Override
    public void setTitle(int titleId) {
        String title = mUIView.getResources().getString(titleId);
        setTitle(title);
    }


    @Override
    public void setLeftText(@NonNull String str, View.OnClickListener clickListener) {
        if (!isMaterialDesign) {
            mLeftButton.setVisibility(View.GONE);
            mLeftText.setVisibility(View.VISIBLE);
            mLeftText.setText(str);
            mLeftText.setOnClickListener(clickListener);
        }
    }

    @Override
    public void setLeftText(@StringRes int strId, View.OnClickListener clickListener) {
        String string = mUIView.getResources().getString(strId);
        setLeftText(string, clickListener);
    }

    @Override
    public void setLeftButton(@NonNull Drawable drawable, View.OnClickListener clickListener) {
        if (isMaterialDesign) {
            mToolbar.setNavigationIcon(drawable);
            mToolbar.setNavigationOnClickListener(clickListener);
            mLeftText.setVisibility(View.GONE);
            mLeftButton.setVisibility(View.GONE);
        } else {
            mLeftText.setVisibility(View.GONE);
            mLeftButton.setVisibility(View.VISIBLE);
            mLeftButton.setImageDrawable(drawable);
            mLeftButton.setOnClickListener(clickListener);
        }
    }

    @Override
    public void setLeftButton(@DrawableRes int drawableId, View.OnClickListener clickListener) {
        setLeftButton(ContextCompat.getDrawable(mUIView.getContext(), drawableId), clickListener);
    }

    @Override
    public void setRightText(@NonNull String str, View.OnClickListener clickListener) {
        if (!isMaterialDesign) {
            mRightButton.setVisibility(View.GONE);
            mRightText.setVisibility(View.VISIBLE);
            mRightText.setText(str);
            mRightText.setOnClickListener(clickListener);
        }
    }

    @Override
    public void setRightText(int strId, View.OnClickListener clickListener) {
        String string = mUIView.getResources().getString(strId);
        setRightText(string, clickListener);
    }

    @Override
    public void setRightButton(@NonNull Drawable drawable, View.OnClickListener clickListener) {
        if (!isMaterialDesign) {
            mRightText.setVisibility(View.GONE);
            mRightButton.setVisibility(View.VISIBLE);
            mRightButton.setImageDrawable(drawable);
        }

    }

    @Override
    public void setRightButton(int drawableId, View.OnClickListener clickListener) {
        setRightButton(ContextCompat.getDrawable(mUIView.getContext(), drawableId), clickListener);
    }
}

BaseActivity的变化

public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity
        implements BaseActivityView {
    protected T mPresenter;
    protected SparseArray<View> mViews;
    private ToolbarHelper mToolbarHelper;
    private boolean isMaterialDesign;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mViews = new SparseArray<>();
        //创建presenter
        mPresenter = initPresenter();
        //绑定Activity
        mPresenter.onAttch(this);
        //是否完全自定义layout
        if (isCustomLayout()) {
            initContentView(LayoutInflater.from(this), savedInstanceState);
        } else {
            super.setContentView(R.layout.activity_base);
            //创建contentView
            View view = initContentView(LayoutInflater.from(this), savedInstanceState);
            //添加contentView
            FrameLayout base_content = findView(R.id.base_content);
            if (view != null) {
                //交给Persenter去扩展
                mPresenter.initContentView(base_content, view);
            }
            //创建toolbar
            createToolbar();
        }
        mPresenter.onCreate();
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                mPresenter.LoadData();
                return false;
            }
        });
    }
    //复写setContentView,如果不设置完全自定义布局,则不能调用setContentView()方法.
   @Override
    public void setContentView(@LayoutRes int layoutResID) {
        //是否完全自定义布局,也就是不使用base_layout
        if (isCustomLayout()) {
            super.setContentView(layoutResID);
        } else {
            throw new IllegalStateException("please setting Presenter Method isCustomLyout() return true ");
        }
    }
    ......

      /**
     * 通过viewId获取控件
     *
     * @param viewId 资源id
     * @return
     */
    @Override
    public <V extends View> V findView(@IdRes int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (V) view;
    }
}  

参考了很多,想了很久,死了很多脑细胞.- -

再附上githubdemo地址,不定期更新

mvpDemo
如果觉得有用就点个星吧.哈哈,


您的喜欢与建议是我最大的动力-_-

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,999评论 4 368
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,102评论 1 302
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,709评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,439评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,846评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,881评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,062评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,783评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,517评论 1 248
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,762评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,241评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,568评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,236评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,145评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,941评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,965评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,802评论 2 275

推荐阅读更多精彩内容