【从 0 开始开发一款直播 APP】5.4 MVC 之 Fragment 交互实现滑动导航

本文为菜鸟窝作者蒋志碧的连载。“从 0 开始开发一款直播 APP ”系列来聊聊时下最火的直播 APP,如何完整的实现一个类"腾讯直播"的商业化项目


【从 0 开始开发一款直播 APP】5.1 MVP 完全解析 -- 实现直播登录
【从 0 开始开发一款直播 APP】5.2 MVP 之 Fragment 交互实现滑动导航
【从 0 开始开发一款直播 APP】5.3 MVC 完全解析 -- 实现直播登录
【从 0 开始开发一款直播 APP】5.4 MVC 之 Fragment 交互实现滑动导航


上一章讲了 MVC 实现登录功能,这一章讲 MVC 实现主页面展示,前面已经实现了这个功能,现在结合 MVC 来讲解。


MVC 之 Fragment 交互实现滑动导航

Controller

1、MVCMainController 对应于 MVCMainActivity

1、定义 MVCIMainController 抽象类,主要方法是 initFragment() — 初始化 FragmentTabHost。

2、定义 MVCMainController 类继承 MVCIMainController 抽象类,实现 initFragment() 方法(FragmentTabHost 数据绑定)的逻辑。

2、MVCLiveMainController 对应于 MVCLivaMainFragment

MVCLiveMainController 与 MVCLiveMainView 关联,并添加初始化 ViewPager 实现导航的数据的方法 initViewPager(View rootView)。

View

1、MVCMainActivity

1、定义 MVCBaseView 接口,将通用方法封装到里面。

2、定义 MVCIMainView 抽象类,实现 MVCBaseView 接口。MVCIMainView 关联 MVCMainController,并绑定 FragmentTabHost 完成数据显示。

3、MVCMainActivity 继承 MVCIMainView 抽象类及其抽象方法,完成 MVCMainController 的实例化以及调用 initFragment() 完成显示 FragmentTabHost 的功能。

2、MVCLivaMainFragment

1、定义 MVCLiveMainView 抽象类继承 BaseFragment 抽象类,关联 MVCLiveMainController,绑定 ViewPager 完成 Tab 的切换。

2、MVCLivaMainFragment 继承 MVCLiveMainView,调用 MVCLiveMainView 中的方法最终完成导航显示。

Model

看到上面运行效果图中,数据就是图片以及标题,还有 Fragment 等,直接在 View 定义。



类图结合上面的文字说明帮助理解,下面开始创建 MVC 基本架构,下面是根据上面类图创建的相关包以及接口和类,红色矩形框中的是 MVCLiveMainFragment 以及 MVCMainActivity 展示数据要用到的类,下面一一进行讲解。

注意:本章讲解是基于前面的一篇文章进行讲解,不做过多的介绍。
具体细节查看:【从 0 开始开发一款直播 APP】2.2 高层封装之 Fragment -- 滑动导航

MVCMainActivity 数据展示

Controller 所有类实现

1、MVCIMainController

Controller 基类,用于绑定 View 和 Model 的逻辑方法封装,initFragment() 用于初始化 FragmentTabHost,完成 底部导航封装方法初步定义。

public abstract class MVCIMainController {
    protected MVCBaseView mBaseView;
    protected BaseActivity mContext;

    public MVCIMainController(MVCBaseView baseView,BaseActivity context) {
        this.mBaseView = baseView;
        this.mContext = context;
    }

    //初始化 FragmentTabHost
    protected abstract void initFragment();
}

2、MVCMainController

MVCMainController 继承 MVCIMainController,实现其抽象方法,mIMainView.setModel() 方法在 MVCIMainView 类中有实现。结合 MVC 架构,C 层完成 V 层的绑定,以及 M 层数据传递的逻辑实现。

public class MVCMainController extends MVCIMainController{

    private MVCIMainView mIMainView;
    public MVCMainController(MVCIMainView mainView, BaseActivity context) {
        super(mainView,context);
        mIMainView = mainView;
    }

    @Override
    public void initFragment() {
        mIMainView.setModel();
    }
}

View 所有类实现

1、MVCBaseView

View 基类定义,封装可能用到的通用方法。

public interface MVCBaseView {

    /**
     * 数据加载或耗时加载时界面显示
     */
    void showLoading();

    /**
     * 数据加载或耗时加载完成时界面显示
     */
    void dismissLoading();

    /**
     * 消息提示,如 Toast,Dialog等
     */
    void showMsg(String msg);
    void showMsg(int msgId);

    /**
     * 获取Context
     * @return
     */
    Context getContext();
}

2、MVCIMainView

MVCIMainView 继承 BaseActivity,实现 MVCBaseView 接口。绑定 MVCMainController 以及 Model 数据展示的具体实现。这里是 FragmentTabHost 实现底部滑动的数据展示。

public abstract class MVCIMainView extends BaseActivity implements MVCBaseView {
    //Controller
    protected MVCMainController mMainController;
    //Model
    public FragmentTabHost mTabHost;
    protected final Class mFragmentArray[] = {MVCLivaMainFragment.class, PublishFragment.class, UserInfoFragment.class};
    protected int mImageViewArray[] = {R.drawable.tab_live_selector, R.drawable.tab_pubish_selector, R.drawable.tab_my_selector};
    protected String mTextViewArray[] = {"live", "publish", "mine"};
    
    //在 MVCMainController 方法中调用
    public void setModel(){
        mTabHost = obtainView(android.R.id.tabhost);
        mTabHost.setup(mContext,getSupportFragmentManager(), R.id.contentPanel);
        int fragmentCount = mFragmentArray.length;
        for (int i = 0; i < fragmentCount; i++) {
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(mTextViewArray[i]).setIndicator(getTabItemView(i,mImageViewArray));
            mTabHost.addTab(tabSpec, mFragmentArray[i], null);
            mTabHost.getTabWidget().setDividerDrawable(null);
        }
    }

    private View getTabItemView(int i,int imageViewArray[]) {
        View view;
        view = LayoutInflater.from(mContext).inflate(R.layout.tab_live, null);
        ImageView imageView = (ImageView) view.findViewById(R.id.tab_icon);
        imageView.setImageResource(imageViewArray[i]);
        return view;
    }
}

3、MVCMainActivity

MVCMainActivity 继承 MVCIMainView,最终完成底部导航在界面上的显示。看到这里代码很少,只有 MVCMainController 的初始化以及调用 initFragment() 方法完成最终显示。

public class MVCMainActivity extends MVCIMainView{
    @Override
    protected void setActionBar() {
    }

    @Override
    protected void setListener() {
    }

    @Override
    protected void initData() {
    }

    @Override
    protected void initView() {
        mMainController = new MVCMainController(this,this);
        mMainController.initFragment();
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_mvcmain;
    }


    @Override
    public void showLoading() {
    }

    @Override
    public void dismissLoading() {
    }

    @Override
    public void showMsg(String msg) {
    }

    @Override
    public void showMsg(int msgId) {
    }

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

运行效果依然不变


上面的导航依然是基于 MVCLiveMainFragment

MVCLiveMainFragment 的数据展示

Controller 所有类实现

MVCLiveMainController

Controller 基类定义,绑定 MVCLiveMainView,mMainView.initViewPager(rootView);mMainView.initViewPagerData() 方法在 MVCLiveMainView 类中有实现。结合 MVC 架构,C 层完成 V 层的绑定,以及 M 层数据传递的逻辑实现。

public class MVCLiveMainController {

    private MVCLiveMainView mMainView;
    //初始化 ViewPager,完成上面导航的显示
    public void initViewPager(View rootView){
        mMainView.initViewPager(rootView);
        mMainView.initViewPagerData();
    }

    public MVCLiveMainController(MVCLiveMainView mainView) {
        this.mMainView = mainView;
    }
}

View 所有类实现

1、MVCLiveMainView

MVCLiveMainView 继承 BaseFragment,绑定 MVCLiveMainController,完成 ViewPager 顶部导航数据显示的具体实现,实例化 MVCLiveMainController。

public abstract class MVCLiveMainView extends BaseFragment {
    //Controller
    protected MVCLiveMainController mMainController;
    //Model
    private ViewPager mViewPager;
    private PagerSlidingTabStrip mTabStrip;
    private ArrayList<String> mTitles;
    private ArrayList<Fragment> mFragments;

    public MVCLiveMainView() {
        mMainController = new MVCLiveMainController(this);
    }

    public void initViewPager(View rootView) {
        mViewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
        mTabStrip = (PagerSlidingTabStrip) rootView.findViewById(R.id.pager_sliding_tab_strip);
        mTabStrip.setTextColorResource(R.color.white);
        mTabStrip.setIndicatorColorResource(R.color.white);
        mTabStrip.setDividerColor(Color.TRANSPARENT);
 mTabStrip.setTextSize(rootView.getResources().getDimensionPixelSize(R.dimen.h6));
        mTabStrip.setUnderlineHeight(1);
        mViewPager.setCurrentItem(0);
    }

    public void initViewPagerData(){
        mTitles = new ArrayList<>();
        mFragments = new ArrayList<>();
        mTitles.add("最新");
        mTitles.add("最热");
        mTitles.add("达人");
        mTitles.add("活力");
        mTitles.add("英雄联盟");
        mTitles.add("王者荣耀");
        for (String s:mTitles){
            Bundle bundle = new Bundle();
            bundle.putString("title",s);
            mFragments.add(LiveListFragment.newInstance(bundle));
        }
        mViewPager.setAdapter(getAdapter());
        mTabStrip.setViewPager(mViewPager);
    }

    public FragmentStatePagerAdapter getAdapter() {
        return new PagerAdapter(mContext.getSupportFragmentManager(),mTitles,mFragments);
    }
}

2、MVCLivaMainFragment

MVCLivaMainFragment 继承 MVCLiveMainView,最终完成顶部导航的展示。

public class MVCLivaMainFragment extends MVCLiveMainView {

    @Override
    protected void initData() {
    }

    @Override
    protected void setListener() {
    }

    @Override
    protected void initView(View rootView) {
        mMainController.initViewPager(rootView);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_mvcliva_main;
    }
}

运行效果


针对 MVC 框架,要做到结构清晰,尽量多画图, 结合 MVC 架构中三者的关系根据具体需求调节实现类和方法。写的有问题的地方还请大家踊跃留言帮助笔者改正。

【五一大促】菜鸟窝全场android项目实战课程低至五折,更有价值33元的四款热门技术免费领,17年初优惠力度最大的一次活动,有意向的童鞋不要错过
狂戳>>http://www.cniao5.com/hd/2017/51.html

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

推荐阅读更多精彩内容