Android开发实战《智慧北京》——2.数据传输

1.主页面上的内容

上一篇博客的末尾实现了一个BasePaper,这次要来编写实现它的5个子类。

  1. 在base目录下新建一个impl目录,然后在该目录下分别新建HomePaper、NewsCenterPaper、SmartServicePaper、GovAffairsPaper、SettingPaper,代码分别如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;

/**
 * 首页
 */
public class HomePaper extends BasePaper {

    public HomePaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("首页");
        flContainer.addView(view); // 给帧布局添加对象
        
        // 设置标题
        tvTitle.setText("首页");
    }
}
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象
        
        // 设置标题
        tvTitle.setText("新闻中心");
    }
}
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;

/**
 * 智慧服务
 */
public class SmartServicePaper extends BasePaper {

    public SmartServicePaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("智慧服务");
        flContainer.addView(view); // 给帧布局添加对象
        
        // 设置标题
        tvTitle.setText("生活");
    }
}
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;

/**
 * 政务
 */
public class GovAffairsPaper extends BasePaper {

    public GovAffairsPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("政务");
        flContainer.addView(view); // 给帧布局添加对象
        
        // 设置标题
        tvTitle.setText("人口管理");
    }
}
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;

/**
 * 设置
 */
public class SettingPaper extends BasePaper {

    public SettingPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("设置");
        flContainer.addView(view); // 给帧布局添加对象
        
        // 设置标题
        tvTitle.setText("设置");
    }
}
  1. 修改ContentFragment,填充5个标签页,代码如下:
package com.example.zhbj.fragment;

import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;

import com.example.zhbj.R;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.GovAffairsPaper;
import com.example.zhbj.base.impl.HomePaper;
import com.example.zhbj.base.impl.NewsCenterPaper;
import com.example.zhbj.base.impl.SettingPaper;
import com.example.zhbj.base.impl.SmartServicePaper;

import java.util.ArrayList;

/**
 * 主页面Fragment
 */
public class ContentFragment extends BaseFragment {

    /**
     * 获取到ViewPaper的对象
     */
    private ViewPager mViewPaper;

    /**
     * 存储5个标签页面的集合
     */
    private ArrayList<BasePaper> mList;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_content, null);
        mViewPaper = (ViewPager) view.findViewById(R.id.vp_content);
        return view;
    }

    /**
     * 初始化ViewPaper的数据
     */
    @Override
    public void initData() {
        // 初始化5个标签页面对象
        mList = new ArrayList<>();
        mList.add(new HomePaper(mActivity));
        mList.add(new NewsCenterPaper(mActivity));
        mList.add(new SmartServicePaper(mActivity));
        mList.add(new GovAffairsPaper(mActivity));
        mList.add(new SettingPaper(mActivity));
        mViewPaper.setAdapter(new ContentAdapter());
    }

    /**
     * ViewPaper的实现类
     */
    class ContentAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
            return view == o;
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            // 获取当前页面的对象
            BasePaper paper = mList.get(position);

            // 初始化布局(给帧布局添加布局对象),以子类实现为准
            paper.initData();

            // 布局对象
            container.addView(paper.mRootView);

            return paper.mRootView;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
        }
    }
}
  1. 为了禁止标签页之间的滑动,新建一个view包,在包下新建NoScrollViewPaper,代码如下:
package com.example.zhbj.view;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * 禁止滑动的ViewPaper
 */
public class NoScrollViewPaper extends ViewPager {

    public NoScrollViewPaper(@NonNull Context context) {
        super(context);
    }

    public NoScrollViewPaper(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // 重写父类的onToucheEvent方法,返回true表示此处什么都不做,达到禁用滑动效果的目的
        return true;
    }
}
  1. 修改fragment_content.xml,调用刚才编写的NoScrollViewPaper,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.zhbj.view.NoScrollViewPaper
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@drawable/bottom_tab_bg">

        <RadioButton
            style="@style/BottomTabStyle"
            android:id="@+id/rb_home"
            android:text="首页"
            android:checked="true"
            android:drawableTop="@drawable/tab_home_selector" />

        <RadioButton
            style="@style/BottomTabStyle"
            android:id="@+id/rb_news"
            android:text="新闻中心"
            android:drawableTop="@drawable/tab_news_selector" />

        <RadioButton
            style="@style/BottomTabStyle"
            android:id="@+id/rb_smart"
            android:text="智慧服务"
            android:drawableTop="@drawable/tab_smart_selector" />

        <RadioButton
            style="@style/BottomTabStyle"
            android:id="@+id/rb_gov"
            android:text="政务"
            android:drawableTop="@drawable/tab_gov_selector" />

        <RadioButton
            style="@style/BottomTabStyle"
            android:id="@+id/rb_setting"
            android:text="设置"
            android:drawableTop="@drawable/tab_setting_selector" />
    </RadioGroup>
</LinearLayout>
  1. 修改ContentFragment,将ViewPaper替换成NoScrollViewPaper,代码如下:
package com.example.zhbj.fragment;

import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

import com.example.zhbj.R;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.GovAffairsPaper;
import com.example.zhbj.base.impl.HomePaper;
import com.example.zhbj.base.impl.NewsCenterPaper;
import com.example.zhbj.base.impl.SettingPaper;
import com.example.zhbj.base.impl.SmartServicePaper;
import com.example.zhbj.view.NoScrollViewPaper;

import java.util.ArrayList;

/**
 * 主页面Fragment
 */
public class ContentFragment extends BaseFragment {

    /**
     * 获取到ViewPaper的对象
     */
    private NoScrollViewPaper mViewPaper;

    /**
     * 存储5个标签页面的集合
     */
    private ArrayList<BasePaper> mList;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_content, null);
        mViewPaper = (NoScrollViewPaper) view.findViewById(R.id.vp_content);
        return view;
    }

    /**
     * 初始化ViewPaper的数据
     */
    @Override
    public void initData() {
        // 初始化5个标签页面对象
        mList = new ArrayList<>();
        mList.add(new HomePaper(mActivity));
        mList.add(new NewsCenterPaper(mActivity));
        mList.add(new SmartServicePaper(mActivity));
        mList.add(new GovAffairsPaper(mActivity));
        mList.add(new SettingPaper(mActivity));
        mViewPaper.setAdapter(new ContentAdapter());
    }

    /**
     * ViewPaper的实现类
     */
    class ContentAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
            return view == o;
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            // 获取当前页面的对象
            BasePaper paper = mList.get(position);

            // 初始化布局(给帧布局添加布局对象),以子类实现为准
            paper.initData();

            // 布局对象
            container.addView(paper.mRootView);

            return paper.mRootView;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
        }
    }
}
  1. 修改fragment_content.xml,为radiogroup添加Id属性,代码如下:
    <RadioGroup
        android:id="@+id/rg_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@drawable/bottom_tab_bg">
  1. 为了简化开发,这里使用开源框架Xutils。导入Xutils的jar包,为了使用Xuntils,需要加上权限。修改AndroidManifest.xml,代码如下:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  1. 修改ContentFragment,使用Xutils来简化代码结构,代码如下:
package com.example.zhbj.fragment;

import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;

import com.example.zhbj.R;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.GovAffairsPaper;
import com.example.zhbj.base.impl.HomePaper;
import com.example.zhbj.base.impl.NewsCenterPaper;
import com.example.zhbj.base.impl.SettingPaper;
import com.example.zhbj.base.impl.SmartServicePaper;
import com.example.zhbj.view.NoScrollViewPaper;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 主页面Fragment
 */
public class ContentFragment extends BaseFragment {

    /**
     * 获取到ViewPaper的对象
     */
    @ViewInject(R.id.vp_content)
    private NoScrollViewPaper mViewPaper;

    /**
     * 存储5个标签页面的集合
     */
    private ArrayList<BasePaper> mList;

    /**
     * Gruop的对象
     */
    @ViewInject(R.id.rg_group)
    private RadioGroup rgGroup;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_content, null);
        ViewUtils.inject(this,view);
        //mViewPaper = (NoScrollViewPaper) view.findViewById(R.id.vp_content);
        //rgGroup = (RadioGroup) view.findViewById(R.id.rg_group);
        return view;
    }

    /**
     * 初始化ViewPaper的数据
     */
    @Override
    public void initData() {
        // 初始化5个标签页面对象
        mList = new ArrayList<>();
        mList.add(new HomePaper(mActivity));
        mList.add(new NewsCenterPaper(mActivity));
        mList.add(new SmartServicePaper(mActivity));
        mList.add(new GovAffairsPaper(mActivity));
        mList.add(new SettingPaper(mActivity));
        mViewPaper.setAdapter(new ContentAdapter());
    }

    /**
     * ViewPaper的实现类
     */
    class ContentAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
            return view == o;
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            // 获取当前页面的对象
            BasePaper paper = mList.get(position);

            // 初始化布局(给帧布局添加布局对象),以子类实现为准
            paper.initData();

            // 布局对象
            container.addView(paper.mRootView);

            return paper.mRootView;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
        }
    }
}
  1. 修改ContentFragment,修改initData()方法,添加点击低栏标签切换页面的功能,代码如下:
    /**
     * 初始化ViewPaper的数据
     */
    @Override
    public void initData() {
        // 初始化5个标签页面对象
        mList = new ArrayList<>();
        mList.add(new HomePaper(mActivity));
        mList.add(new NewsCenterPaper(mActivity));
        mList.add(new SmartServicePaper(mActivity));
        mList.add(new GovAffairsPaper(mActivity));
        mList.add(new SettingPaper(mActivity));
        mViewPaper.setAdapter(new ContentAdapter());

        rgGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.rb_home:
                        // 首页
                        mViewPaper.setCurrentItem(0,false);
                        break;
                    case R.id.rb_news:
                        // 新闻中心
                        mViewPaper.setCurrentItem(1,false);
                        break;
                    case R.id.rb_smart:
                        // 智慧服务
                        mViewPaper.setCurrentItem(2,false);
                        break;
                    case R.id.rb_gov:
                        // 政务
                        mViewPaper.setCurrentItem(3,false);
                        break;
                    case R.id.rb_setting:
                        // 设置
                        mViewPaper.setCurrentItem(4,false);
                        break;
                    default:break;
                }
            }
        });
    }

2.主页面上的优化

现在页面结构大体完成了,但是需要一些优化,我们现在开始实现吧。

  1. 数据初始化的优化:因为在点击某个ViewPager时,会同时初始化下一页的数据,这样会造成数据的溢出和流量的缺失。针对这一点,修改ContentFragment,在instantiateItem()方法中注解掉initData()方法,并添加setOnPageChangeListener()监听器,监听选中每个按钮时执行initData()方法,注意要提前初始化好第一页的数据,代码如下:
package com.example.zhbj.fragment;

import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;

import com.example.zhbj.R;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.GovAffairsPaper;
import com.example.zhbj.base.impl.HomePaper;
import com.example.zhbj.base.impl.NewsCenterPaper;
import com.example.zhbj.base.impl.SettingPaper;
import com.example.zhbj.base.impl.SmartServicePaper;
import com.example.zhbj.view.NoScrollViewPaper;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 主页面Fragment
 */
public class ContentFragment extends BaseFragment {

    /**
     * 获取到ViewPaper的对象
     */
    @ViewInject(R.id.vp_content)
    private NoScrollViewPaper mViewPaper;

    /**
     * 存储5个标签页面的集合
     */
    private ArrayList<BasePaper> mList;

    /**
     * Gruop的对象
     */
    @ViewInject(R.id.rg_group)
    private RadioGroup rgGroup;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_content, null);
        ViewUtils.inject(this,view);
        //mViewPaper = (NoScrollViewPaper) view.findViewById(R.id.vp_content);
        //rgGroup = (RadioGroup) view.findViewById(R.id.rg_group);
        return view;
    }

    /**
     * 初始化ViewPaper的数据
     */
    @Override
    public void initData() {
        // 初始化5个标签页面对象
        mList = new ArrayList<>();
        mList.add(new HomePaper(mActivity));
        mList.add(new NewsCenterPaper(mActivity));
        mList.add(new SmartServicePaper(mActivity));
        mList.add(new GovAffairsPaper(mActivity));
        mList.add(new SettingPaper(mActivity));
        mViewPaper.setAdapter(new ContentAdapter());

        rgGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.rb_home:
                        // 首页
                        mViewPaper.setCurrentItem(0,false);
                        break;
                    case R.id.rb_news:
                        // 新闻中心
                        mViewPaper.setCurrentItem(1,false);
                        break;
                    case R.id.rb_smart:
                        // 智慧服务
                        mViewPaper.setCurrentItem(2,false);
                        break;
                    case R.id.rb_gov:
                        // 政务
                        mViewPaper.setCurrentItem(3,false);
                        break;
                    case R.id.rb_setting:
                        // 设置
                        mViewPaper.setCurrentItem(4,false);
                        break;
                    default:break;
                }
            }
        });

        // 监听Viewpager页面切换时间,初始化当前页面数据
        mViewPaper.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i1) {

            }

            @Override
            public void onPageSelected(int i) {
                BasePaper paper = mList.get(i);
                paper.initData();
            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });
        // 手动初始化第一个页面的数据
        mList.get(0).initData();
    }

    /**
     * ViewPaper的实现类
     */
    class ContentAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
            return view == o;
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            // 获取当前页面的对象
            BasePaper paper = mList.get(position);

            // 此方法导致每次都提前加载下一页数据,浪费流量和性能,不建议在此处初始化数据
            // paper.initData(); // 初始化布局(给帧布局添加布局对象),以子类实现为准

            // 布局对象
            container.addView(paper.mRootView);

            return paper.mRootView;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
        }
    }
}
  1. 根据当前页面的显示位置启用和禁用侧边栏:根据当前的页面,应该可以启用和禁用侧边栏,这样才显得应用程序较为智能。修改HomePaper和SettingPaper的initData()方法,隐藏菜单按钮,代码如下:
        // 隐藏菜单按钮
        btnMenu.setVisibility(View.GONE);

然后修改ContentFragment,添加setSlidingMenuEnable(),表示启用/禁用侧边栏,然后修改相应逻辑,注意到第一个页面时依然要手动禁用侧边栏,整体代码如下:

package com.example.zhbj.fragment;

import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;

import com.example.zhbj.MainActivity;
import com.example.zhbj.R;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.GovAffairsPaper;
import com.example.zhbj.base.impl.HomePaper;
import com.example.zhbj.base.impl.NewsCenterPaper;
import com.example.zhbj.base.impl.SettingPaper;
import com.example.zhbj.base.impl.SmartServicePaper;
import com.example.zhbj.view.NoScrollViewPaper;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 主页面Fragment
 */
public class ContentFragment extends BaseFragment {

    /**
     * 获取到ViewPaper的对象
     */
    @ViewInject(R.id.vp_content)
    private NoScrollViewPaper mViewPaper;

    /**
     * 存储5个标签页面的集合
     */
    private ArrayList<BasePaper> mList;

    /**
     * Gruop的对象
     */
    @ViewInject(R.id.rg_group)
    private RadioGroup rgGroup;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_content, null);
        ViewUtils.inject(this,view);
        //mViewPaper = (NoScrollViewPaper) view.findViewById(R.id.vp_content);
        //rgGroup = (RadioGroup) view.findViewById(R.id.rg_group);
        return view;
    }

    /**
     * 初始化ViewPaper的数据
     */
    @Override
    public void initData() {
        // 初始化5个标签页面对象
        mList = new ArrayList<>();
        mList.add(new HomePaper(mActivity));
        mList.add(new NewsCenterPaper(mActivity));
        mList.add(new SmartServicePaper(mActivity));
        mList.add(new GovAffairsPaper(mActivity));
        mList.add(new SettingPaper(mActivity));
        mViewPaper.setAdapter(new ContentAdapter());

        rgGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.rb_home:
                        // 首页
                        mViewPaper.setCurrentItem(0,false);
                        break;
                    case R.id.rb_news:
                        // 新闻中心
                        mViewPaper.setCurrentItem(1,false);
                        break;
                    case R.id.rb_smart:
                        // 智慧服务
                        mViewPaper.setCurrentItem(2,false);
                        break;
                    case R.id.rb_gov:
                        // 政务
                        mViewPaper.setCurrentItem(3,false);
                        break;
                    case R.id.rb_setting:
                        // 设置
                        mViewPaper.setCurrentItem(4,false);
                        break;
                    default:break;
                }
            }
        });

        // 监听Viewpager页面切换时间,初始化当前页面数据
        mViewPaper.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i1) {

            }

            @Override
            public void onPageSelected(int i) {
                BasePaper paper = mList.get(i);
                paper.initData();

                if (i == 0 || i == mList.size() - 1){
                    // 禁用侧边栏
                    setSlidingMenuEnable(false);
                }else {
                    // 启用侧边栏
                    setSlidingMenuEnable(true);
                }
            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });
        // 手动初始化第一个页面的数据
        mList.get(0).initData();

        // 手动禁用第一个页面的侧边栏
        setSlidingMenuEnable(false);
    }

    /**
     * 开启/禁用侧边栏
     */
    private void setSlidingMenuEnable(boolean enable){
        // 获取MainActivity对象
        MainActivity mainUI = (MainActivity) mActivity;

        // 获取SlidingMenu对象
        SlidingMenu slidingMenu = mainUI.getSlidingMenu();
        if (enable){
            slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
        }else {
            slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
        }

    }

    /**
     * ViewPaper的实现类
     */
    class ContentAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
            return view == o;
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            // 获取当前页面的对象
            BasePaper paper = mList.get(position);

            // 此方法导致每次都提前加载下一页数据,浪费流量和性能,不建议在此处初始化数据
            // paper.initData(); // 初始化布局(给帧布局添加布局对象),以子类实现为准

            // 布局对象
            container.addView(paper.mRootView);

            return paper.mRootView;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
        }
    }
}

3.主页面上的UI结构

经过前面的编写,我们已经完成了三个页面,现在来回顾一下当前页面的结构:
在这里插入图片描述

4.服务器的配置

为了让应用程序能够访问到应用数据,这里将资源文件夹zhbj放到Tomcat下的webapps/root目录下。放置完成后,确认能访问到localhost:8080/zhbj/categories.json,如图所示:

在这里插入图片描述

至此,服务器数据就配置完成了。

  1. 修改NewsCenterPaper,添加getDataFromServer()方法,用于从服务器获取数据,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象

        // 设置标题
        tvTitle.setText("新闻中心");

        // 从服务器获取数据
        getDataFromServer();
    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, "http://10.0.2.2:8080/zhbj/categories.json",
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {

                    }
                });
    }
}
  1. 为了方便以后调用常用的量,新建一个包名为global,在其下新建一个类为GlobalConstans,里面是一些常用的常量,代码如下:
package com.example.zhbj.global;

public class GlobalConstans {
    
    // 服务器根地址,域名
    public static final String SERVER_URL = "http://10.0.2.2:8080/zhbj/";
    
    // 分类接口地址
    public static final String CATEGORY_URL =  SERVER_URL + "categories.json";
}

与此同时,修改NewsCenterPaper,修改对应引用:

utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {

                    }

                    @Override
                    public void onFailure(HttpException e, String s) {

                    }
                });

5.服务器的数据解析

为了解析服务器上的JSON数据,这里引入GSON,用于解析JSON数据。

  1. 为了包装JSON数据,这里新建一个Domain包,然后新建一个类NewsMenu,代表封装了新闻菜单的实体类,注意要和JSON数据一样,代码如下:
package com.example.zhbj.domain;

import java.util.ArrayList;

/**
 * 新闻分类封装的实体类
 */
public class NewsMenu {

    public int retcode;

    public ArrayList<NewsMenuData> data;
    
    public ArrayList<String> extend;

    /**
     * 四个分类菜单的信息
     */
    public class NewsMenuData{

        public String id;

        public String title;

        public int type;

        public ArrayList<NewsTabData> children;
    }

    /**
     * 十二个页签的对象封装
     */
    public class NewsTabData{

        public String id;

        public String title;

        public int type;

        public String url;

    }
}
  1. 引入GSON后,修改NewsCenterPager,增加processData()方法,用于解析JSON数据,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.base.BasePaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.global.GlobalConstans;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象

        // 设置标题
        tvTitle.setText("新闻中心");

        // 从服务器获取数据
        getDataFromServer();
    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        NewsMenu newsMenu = gson.fromJson(json, NewsMenu.class);
    }
}

6.从新闻中心页面将网络数据传递给侧边栏

现在想要将解析好的数据传给侧边栏,现在开始实现逻辑。

  1. 修改fragment_left_menu.xml,增加一个listview控件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000">

    <ListView
        android:id="@+id/lv_menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
  1. 为了设置ListView中每一项的子布局,新建list_item_left_menu.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#000"
    android:gravity="center">

    <TextView
        android:id="@+id/tv_menu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:padding="10dp"
        android:drawableLeft="@drawable/menu_arr_normal"
        android:drawablePadding="5dp"
        android:textColor="#fff"
        android:textSize="22sp"/>

</LinearLayout>
  1. 修改LeftMenuFragment,获取ListView的实例,然后添加适配器,代码如下:
package com.example.zhbj.fragment;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.zhbj.R;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

/**
 * 侧边栏Fragment
 */
public class LeftMenuFragment extends BaseFragment {

    @ViewInject(R.id.lv_menu)
    private ListView lvList;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_left_menu, null);
        ViewUtils.inject(this,view);
        return view;
    }

    class LeftMenuAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = View.inflate(mActivity, R.layout.list_item_left_menu, null);
            TextView tvMenu = (TextView) view.findViewById(R.id.tv_menu);
            return view;
        }
    }
}
  1. 修改MainActivity,添加getLeftMenuFragment()方法,用于获取侧边栏的碎片,代码如下:
package com.example.zhbj;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Window;

import com.example.zhbj.fragment.ContentFragment;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;

/**
 * 主页面
 *
 * 当一个activity要展示Fragment时,必须要继承FragmentActivity
 */
public class MainActivity extends SlidingFragmentActivity {

    /**
     * 定义“内容”碎片的标志
     */
    private static final String TAG_CONTENT = "TAG_CONTENT";

    /**
     * 定义“侧边栏”碎片的标志
     */
    private static final String TAG_LEFT_MENU = "TAG_LEFT_MENU";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        // 设置侧边栏的布局
        setBehindContentView(R.layout.left_menu);

        // 获取当前侧边栏对象
        SlidingMenu slidingMenu = getSlidingMenu();
        // 设置侧边栏的触摸模式为全屏触摸
        slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
        // 设置侧边栏为左右都有的模式,不然默认只展现一个
        // slidingMenu.setMode(SlidingMenu.LEFT_RIGHT);
        // 设置右侧的侧边栏
        // slidingMenu.setSecondaryMenu(res);
        // 设置侧边栏的宽度
        slidingMenu.setBehindOffset(260);// 屏幕预留200px的宽度
        initFragment();
    }

    /**
     * 初始化Fragment
     */
    private void initFragment(){
        // 获取Fragment管理器
        FragmentManager fragmentManager = getSupportFragmentManager();
        // FragmentManager开启一个事务
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fl_content,new ContentFragment(),TAG_CONTENT); // 使用fragment替换现有布局,第一个参数表示当前布局的id,第二个参数表示要替换的Fragment对象
        fragmentTransaction.replace(R.id.fl_left_menu,new LeftMenuFragment(),TAG_LEFT_MENU); // 第三个参数为打一个标记,可以调用这个碎片对象
        fragmentTransaction.commit(); // 提交事务
        //fragmentManager.findFragmentByTag(TAG); // 通过Tag找到fragment对象
    }

    /**
     * 获取侧边栏对象
     */
    public LeftMenuFragment getLeftMenuFragment(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        LeftMenuFragment fragment = (LeftMenuFragment) fragmentManager.findFragmentByTag(TAG_LEFT_MENU);
        return fragment;
    }
}
  1. 修改NewsConterPaper,修改processData()方法,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.example.zhbj.global.GlobalConstans;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象

        // 设置标题
        tvTitle.setText("新闻中心");

        // 从服务器获取数据
        getDataFromServer();
    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        NewsMenu newsMenu = gson.fromJson(json, NewsMenu.class);

        // 找到侧边栏对象
        MainActivity mainUI = (MainActivity) mActivity;
        LeftMenuFragment fragment = mainUI.getLeftMenuFragment();
        fragment.setMenuData(newsMenu.data);

    }
}
  1. 修改LeftMenuFragment,添加setMenuData(),用于设置侧边栏数据,代码如下:
    /**
     * 侧边栏的数据对象
     */
    private ArrayList<NewsMenu.NewsMenuData> data;    

	/**
     * 设置侧边栏数据,通过此方法,可以将新闻中心页面将网格数据传递过来
     * @param data
     */
    public void setMenuData(ArrayList<NewsMenu.NewsMenuData> data) {
        this.data = data;
    }
  1. 修改LeftManuFragment,修改LeftMenuAdapter类中的setMenuData()、getCount()、getItem()、getView()方法,代码如下:
package com.example.zhbj.fragment;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.zhbj.R;
import com.example.zhbj.domain.NewsMenu;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 侧边栏Fragment
 */
public class LeftMenuFragment extends BaseFragment {

    @ViewInject(R.id.lv_menu)
    private ListView lvList;

    /**
     * 侧边栏的数据对象
     */
    private ArrayList<NewsMenu.NewsMenuData> data;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_left_menu, null);
        ViewUtils.inject(this,view);
        return view;
    }

    /**
     * 设置侧边栏数据,通过此方法,可以将新闻中心页面将网格数据传递过来
     * @param data
     */
    public void setMenuData(ArrayList<NewsMenu.NewsMenuData> data) {
        this.data = data;
        lvList.setAdapter(new LeftMenuAdapter());
    }

    class LeftMenuAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return data.size();
        }

        @Override
        public NewsMenu.NewsMenuData getItem(int position) {
            return data.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = View.inflate(mActivity, R.layout.list_item_left_menu, null);
            TextView tvMenu = (TextView) view.findViewById(R.id.tv_menu);
            NewsMenu.NewsMenuData info = getItem(position);
            tvMenu.setText(info.title);
            return view;
        }
    }
}
  1. 在drawable目录下,新建选择器menu_arr_selector.xml,用这个状态选择器来绑定在侧边栏中每个按钮被点击的时候变色,注意由于该组件是ListView,所以选定属性需要选用组件通用的stable_enabled属性,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_enabled="true" android:drawable="@drawable/menu_arr_select"/>
    <item android:drawable="@drawable/menu_arr_normal"/>

</selector>

与此同时,在color目录下,新建选择器menu_txt_selector.xml,用这个状态选择器来绑定在侧边栏中每个按钮里的文字被点击的时候变色,注意由于该组件是ListView,所以选定属性需要选用组件通用的stable_enabled属性,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_enabled="true" android:color="#f00"/>
    <item android:color="#fff"/>

</selector>

最后,修改list_item_left_menu.xml,修改相应的组件,绑定选择器,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#000"
    android:gravity="center">

    <TextView
        android:id="@+id/tv_menu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:padding="10dp"
        android:drawableLeft="@drawable/menu_arr_selector"
        android:drawablePadding="5dp"
        android:textColor="@color/menu_txt_selector"
        android:enabled="false"
        android:textSize="22sp"/>

</LinearLayout>
  1. 修改LeftManuFragment,修改LeftMenuAdapter类中的getView(),添加点击某个按钮来判断某个TextView组件是否可用。注意添加一个全局的变量,用于判断点击的位置坐标。同时修改setMenuData()方法,用于给全局变量赋值,代码如下:
package com.example.zhbj.fragment;

import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.zhbj.R;
import com.example.zhbj.domain.NewsMenu;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 侧边栏Fragment
 */
public class LeftMenuFragment extends BaseFragment {

    @ViewInject(R.id.lv_menu)
    private ListView lvList;

    /**
     * 侧边栏的数据对象
     */
    private ArrayList<NewsMenu.NewsMenuData> data;

    /**
     * 当前选中的菜单位置
     */
    private int mCurrentPos;

    /**
     * 侧边栏的适配器对象
     */
    private LeftMenuAdapter mAdapter;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_left_menu, null);
        ViewUtils.inject(this,view);
        return view;
    }

    /**
     * 设置侧边栏数据,通过此方法,可以将新闻中心页面将网格数据传递过来
     * @param data
     */
    public void setMenuData(ArrayList<NewsMenu.NewsMenuData> data) {
        this.data = data;
        mAdapter = new LeftMenuAdapter();
        lvList.setAdapter(mAdapter);
        lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mCurrentPos = position; // 更新当前的点击位置
                // 刷新ListView
                mAdapter.notifyDataSetChanged();
            }
        });
    }

    class LeftMenuAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return data.size();
        }

        @Override
        public NewsMenu.NewsMenuData getItem(int position) {
            return data.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = View.inflate(mActivity, R.layout.list_item_left_menu, null);
            TextView tvMenu = (TextView) view.findViewById(R.id.tv_menu);

            // 设置TextView的可用或者不可用的颜色
            if (mCurrentPos == position){
                // 当前item被选中
                tvMenu.setEnabled(true);
            }else {
                // 当前item未选中
                tvMenu.setEnabled(false);
            }

            NewsMenu.NewsMenuData info = getItem(position);
            tvMenu.setText(info.title);
            return view;
        }
    }
}
  1. 修改LeftManuFragment,添加toggle()方法,用于增加点击菜单栏后被收回的逻辑,代码如下:
package com.example.zhbj.fragment;

import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.R;
import com.example.zhbj.domain.NewsMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 侧边栏Fragment
 */
public class LeftMenuFragment extends BaseFragment {

    @ViewInject(R.id.lv_menu)
    private ListView lvList;

    /**
     * 侧边栏的数据对象
     */
    private ArrayList<NewsMenu.NewsMenuData> data;

    /**
     * 当前选中的菜单位置
     */
    private int mCurrentPos;

    /**
     * 侧边栏的适配器对象
     */
    private LeftMenuAdapter mAdapter;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_left_menu, null);
        ViewUtils.inject(this,view);
        return view;
    }

    /**
     * 设置侧边栏数据,通过此方法,可以将新闻中心页面将网格数据传递过来
     * @param data
     */
    public void setMenuData(ArrayList<NewsMenu.NewsMenuData> data) {
        this.data = data;
        mAdapter = new LeftMenuAdapter();
        lvList.setAdapter(mAdapter);
        lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mCurrentPos = position; // 更新当前的点击位置
                // 刷新ListView
                mAdapter.notifyDataSetChanged();

                // 收回侧边栏
                toggle();
            }
        });
    }

    /**
     * 控制侧边栏的开关
     */
    private void toggle() {
        MainActivity mainUI = (MainActivity) mActivity;
        SlidingMenu slidingMenu = mainUI.getSlidingMenu();
        slidingMenu.toggle(); // 如果当前为开,则关;反之亦然
    }

    /**
     * 侧边栏的适配器类
     */
    class LeftMenuAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return data.size();
        }

        @Override
        public NewsMenu.NewsMenuData getItem(int position) {
            return data.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = View.inflate(mActivity, R.layout.list_item_left_menu, null);
            TextView tvMenu = (TextView) view.findViewById(R.id.tv_menu);

            // 设置TextView的可用或者不可用的颜色
            if (mCurrentPos == position){
                // 当前item被选中
                tvMenu.setEnabled(true);
            }else {
                // 当前item未选中
                tvMenu.setEnabled(false);
            }

            NewsMenu.NewsMenuData info = getItem(position);
            tvMenu.setText(info.title);
            return view;
        }
    }
}
  1. 修改BasePaper,修改initView()方法,添加toggle()方法,并为菜单按钮注册点击事件,用于开关侧边栏,代码如下:
package com.example.zhbj.base;

import android.app.Activity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.R;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;

/**
 * 5个标签页的基类
 *
 * 共性:子类都有标题栏,所以可以直接在父类中加载布局页面
 */
public class BasePaper {

    /**
     * Activity对象
     */
    public Activity mActivity;

    /**
     * 标题的对象
     */
    public TextView tvTitle;

    /**
     * 标题按钮的对象
     */
    public ImageButton btnMenu;

    /**
     * 当前页面的根布局
     */
    public View mRootView;

    /**
     * 内容的对象
     */
    public FrameLayout flContainer;

    public BasePaper(Activity activity) {
        mActivity = activity;
        // 在页面对象创建时,就初始化了布局
        mRootView = initView();
    }

    /**
     * 初始化布局
     */
    public View initView(){
        View view = View.inflate(mActivity, R.layout.base_paper, null);
        tvTitle = (TextView) view.findViewById(R.id.tv_title);
        btnMenu = (ImageButton) view.findViewById(R.id.btn_menu);
        flContainer = (FrameLayout) view.findViewById(R.id.fl_container);
        // 点击菜单按钮,控制侧边栏开关
        btnMenu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggle();
            }
        });
        return view;
    }

    /**
     * 控制侧边栏的开关
     */
    private void toggle() {
        MainActivity mainUI = (MainActivity) mActivity;
        SlidingMenu slidingMenu = mainUI.getSlidingMenu();
        slidingMenu.toggle(); // 如果当前为开,则关;反之亦然
    }

    /**
     * 初始化数据
     */
    public void initData(){

    }
}

7.通过侧边栏找到新闻中心页面对象

实现了侧边栏获取到JSON数据后,接下来就应该实现点击侧边栏的每个按钮便显示不同的界面,让我们开始实现逻辑吧。

  1. 修改MainActivity,添加getContentFragment()方法,用于获取主页的fragment对象,代码如下:
    /**
     * 获取主页的fragment对象
     */
    public ContentFragment getContentFragment(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        ContentFragment fragment = (ContentFragment) fragmentManager.findFragmentByTag(TAG_CONTENT);
        return fragment;
    }
  1. 修改ContentFragment,添加getNewsCenterPager()方法,用于获取新闻中心对象,代码如下:
    /**
     * 获取新闻中心对象
     */
    public NewsCenterPaper getNewsCenterPager(){
        NewsCenterPaper paper = (NewsCenterPaper) mList.get(1); // 新闻中心在集合的第二个位置
        return paper;
    }
  1. 修改NewsCenterPaper,添加setMenuDetailPager()方法,用于设置新闻中心的详情页,代码如下:
    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){

    }
  1. 修改LeftMenuFragment,添加setMenuDetailPager()方法,用于修改新闻中心的帧布局,代码如下:
package com.example.zhbj.fragment;

import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.R;
import com.example.zhbj.base.impl.NewsCenterPaper;
import com.example.zhbj.domain.NewsMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;

import java.util.ArrayList;

/**
 * 侧边栏Fragment
 */
public class LeftMenuFragment extends BaseFragment {

    @ViewInject(R.id.lv_menu)
    private ListView lvList;

    /**
     * 侧边栏的数据对象
     */
    private ArrayList<NewsMenu.NewsMenuData> data;

    /**
     * 当前选中的菜单位置
     */
    private int mCurrentPos;

    /**
     * 侧边栏的适配器对象
     */
    private LeftMenuAdapter mAdapter;

    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_left_menu, null);
        ViewUtils.inject(this,view);
        return view;
    }

    /**
     * 设置侧边栏数据,通过此方法,可以将新闻中心页面将网格数据传递过来
     * @param data
     */
    public void setMenuData(ArrayList<NewsMenu.NewsMenuData> data) {
        this.data = data;
        mAdapter = new LeftMenuAdapter();
        lvList.setAdapter(mAdapter);
        lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mCurrentPos = position; // 更新当前的点击位置
                // 刷新ListView
                mAdapter.notifyDataSetChanged();

                // 收回侧边栏
                toggle();
                
                // 修改侧边栏的帧布局
                setMenuDetailPager(position);
            }
        });
    }

    /**
     * 修改菜单详情页
     * @param position
     */
    private void setMenuDetailPager(int position) {
        // 修改侧边栏的帧布局
        // 获取新闻中心的对象
        MainActivity mainUI = (MainActivity) mActivity;
        ContentFragment fragment = mainUI.getContentFragment();
        NewsCenterPaper pager = fragment.getNewsCenterPager();
        pager.setMenuDetailPager(position);
    }

    /**
     * 控制侧边栏的开关
     */
    private void toggle() {
        MainActivity mainUI = (MainActivity) mActivity;
        SlidingMenu slidingMenu = mainUI.getSlidingMenu();
        slidingMenu.toggle(); // 如果当前为开,则关;反之亦然
    }

    /**
     * 侧边栏的适配器类
     */
    class LeftMenuAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return data.size();
        }

        @Override
        public NewsMenu.NewsMenuData getItem(int position) {
            return data.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = View.inflate(mActivity, R.layout.list_item_left_menu, null);
            TextView tvMenu = (TextView) view.findViewById(R.id.tv_menu);

            // 设置TextView的可用或者不可用的颜色
            if (mCurrentPos == position){
                // 当前item被选中
                tvMenu.setEnabled(true);
            }else {
                // 当前item未选中
                tvMenu.setEnabled(false);
            }

            NewsMenu.NewsMenuData info = getItem(position);
            tvMenu.setText(info.title);
            return view;
        }
    }
}

8.菜单详情页页面对象封装

为了点击侧边栏的不同选项时显示不同的页面,需要封装4个页面对象,现在开始实现逻辑。

  1. 在base包下新建BaseMenuDetailPaper,用于实现菜单详情页的基类,代码如下:
package com.example.zhbj.base;

import android.app.Activity;
import android.view.View;

/**
 * 菜单详情页基类,在新闻专题组图互动
 */
public abstract class BaseMenuDetailPaper {

    /**
     * Activity对象
     */
    public Activity mActivity;

    /**
     * 菜单详情页的根布局
     */
    public View mRootView;

    public BaseMenuDetailPaper(Activity activity) {
        mActivity = activity;
        mRootView = initViews();
    }

    /**
     * 初始化布局,必须由子类实现
     */
    public abstract View initViews();
    /**
     * 初始化页面
     */
    public void initData(){

    }
}
  1. 在base/impl下新建menudetail包,分别创建InteractMenuDetailPaper、NewsMenuDetailPaper、PhotosMenuDetailPaper、TopicMenuDetailPaper,分别代表互动、新闻、组图、专题页面,需要继承BaseMenuDetailPaper,如图所示:

在这里插入图片描述

  1. 分别修改上面刚刚创建的四个类,设置其布局,这里仅演示修改一个类,其他代码同理,代码如下:
package com.example.zhbj.base.impl.menudetail;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;

import com.example.zhbj.base.BaseMenuDetailPaper;

/**
 * 菜单详情页 - 新闻
 */
public class NewsMenuDetailPaper extends BaseMenuDetailPaper {

    public NewsMenuDetailPaper(Activity activity) {
        super(activity);
    }

    @Override
    public View initViews() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("菜单详情页-新闻");
        return view;
    }
}

9.点击侧边栏切换菜单详情页

封装好菜单详情页的页面对象后,现在就需要实现点击侧边栏切换菜单详情页的逻辑,现在开始实现。

  1. 修改NewsCenterPaper,修改processData()方法,让网络请求成功后初始化四个页面对象,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.base.BaseMenuDetailPaper;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.menudetail.InteractMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.NewsMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.PhotosMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.TopicMenuDetailPaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.example.zhbj.global.GlobalConstans;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

import java.util.ArrayList;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    /**
     * 存放四个菜单详情页对象的集合
     */
    private ArrayList<BaseMenuDetailPaper>  mPapers;

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象

        // 设置标题
        tvTitle.setText("新闻中心");

        // 从服务器获取数据
        getDataFromServer();
    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        NewsMenu newsMenu = gson.fromJson(json, NewsMenu.class);

        // 找到侧边栏对象
        MainActivity mainUI = (MainActivity) mActivity;
        LeftMenuFragment fragment = mainUI.getLeftMenuFragment();
        fragment.setMenuData(newsMenu.data);

        // 网络请求成功之后,初始化四个菜单详情页
        mPapers = new ArrayList<>();
        mPapers.add(new NewsMenuDetailPaper(mActivity));
        mPapers.add(new TopicMenuDetailPaper(mActivity));
        mPapers.add(new PhotosMenuDetailPaper(mActivity));
        mPapers.add(new InteractMenuDetailPaper(mActivity));
    }
    
        // 设置新闻菜单详情页为默认页面
        setMenuDetailPager(0);

    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){

    }
}
  1. 修改NewsCenterPaper,完善setMenuDetailPager()方法,添加修改点击侧边栏切换菜单详情页的逻辑,代码如下:
    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){
        BaseMenuDetailPaper paper = mPapers.get(position);

        // 清除之前帧布局显示的内容
        flContainer.removeAllViews();

        // 修改当前帧布局显示的内容
        flContainer.addView(paper.mRootView);

        // 初始化当前页面的数据
        paper.initData();
    }
  1. 修改NewsCenterPaper,让新闻详情页面作为默认的首页,同时删除initData()方法中的布局绘制逻辑,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.base.BaseMenuDetailPaper;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.menudetail.InteractMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.NewsMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.PhotosMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.TopicMenuDetailPaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.example.zhbj.global.GlobalConstans;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

import java.util.ArrayList;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    /**
     * 存放四个菜单详情页对象的集合
     */
    private ArrayList<BaseMenuDetailPaper>  mPapers;

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        /*
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象
        */

        // 设置标题
        tvTitle.setText("新闻中心");

        // 从服务器获取数据
        getDataFromServer();
    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        NewsMenu newsMenu = gson.fromJson(json, NewsMenu.class);

        // 找到侧边栏对象
        MainActivity mainUI = (MainActivity) mActivity;
        LeftMenuFragment fragment = mainUI.getLeftMenuFragment();
        fragment.setMenuData(newsMenu.data);

        // 网络请求成功之后,初始化四个菜单详情页
        mPapers = new ArrayList<>();
        mPapers.add(new NewsMenuDetailPaper(mActivity));
        mPapers.add(new TopicMenuDetailPaper(mActivity));
        mPapers.add(new PhotosMenuDetailPaper(mActivity));
        mPapers.add(new InteractMenuDetailPaper(mActivity));

        // 设置新闻菜单详情页为默认页面
        setMenuDetailPager(0);
    }

    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){
        BaseMenuDetailPaper paper = mPapers.get(position);

        // 清除之前帧布局显示的内容
        flContainer.removeAllViews();

        // 修改当前帧布局显示的内容
        flContainer.addView(paper.mRootView);

        // 初始化当前页面的数据
        paper.initData();
    }
}
  1. 修改NewsCenterPaper,当新闻详情页修改时标题也跟着一起修改,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.base.BaseMenuDetailPaper;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.menudetail.InteractMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.NewsMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.PhotosMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.TopicMenuDetailPaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.example.zhbj.global.GlobalConstans;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

import java.util.ArrayList;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    /**
     * 存放四个菜单详情页对象的集合
     */
    private ArrayList<BaseMenuDetailPaper>  mPapers;

    /**
     * 从服务器上获取到的JSON数据
     */
    private NewsMenu newsMenu;

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        /*
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象
        */

        // 设置标题
        tvTitle.setText("新闻");

        // 从服务器获取数据
        getDataFromServer();
    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        newsMenu = gson.fromJson(json, NewsMenu.class);

        // 找到侧边栏对象
        MainActivity mainUI = (MainActivity) mActivity;
        LeftMenuFragment fragment = mainUI.getLeftMenuFragment();
        fragment.setMenuData(newsMenu.data);

        // 网络请求成功之后,初始化四个菜单详情页
        mPapers = new ArrayList<>();
        mPapers.add(new NewsMenuDetailPaper(mActivity));
        mPapers.add(new TopicMenuDetailPaper(mActivity));
        mPapers.add(new PhotosMenuDetailPaper(mActivity));
        mPapers.add(new InteractMenuDetailPaper(mActivity));

        // 设置新闻菜单详情页为默认页面
        setMenuDetailPager(0);
    }

    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){
        BaseMenuDetailPaper paper = mPapers.get(position);

        // 清除之前帧布局显示的内容
        flContainer.removeAllViews();

        // 修改当前帧布局显示的内容
        flContainer.addView(paper.mRootView);

        // 初始化当前页面的数据
        paper.initData();

        // 修改标题栏
        tvTitle.setText(newsMenu.data.get(position).title);
    }
}

  1. 修改LeftMenuFragment,修改setMenuData(),每次获取数据时都重置一下位置,修复详情页和侧边栏不同步的bug,代码如下:
/**
     * 设置侧边栏数据,通过此方法,可以将新闻中心页面将网格数据传递过来
     * @param data
     */
    public void setMenuData(ArrayList<NewsMenu.NewsMenuData> data) {
        this.data = data;

        // 重置当前选中位置归0,避免侧边栏选中位置和菜单详情页不同步
        mCurrentPos = 0;

        mAdapter = new LeftMenuAdapter();
        lvList.setAdapter(mAdapter);
        lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mCurrentPos = position; // 更新当前的点击位置
                // 刷新ListView
                mAdapter.notifyDataSetChanged();

                // 收回侧边栏
                toggle();
                
                // 修改侧边栏的帧布局
                setMenuDetailPager(position);
            }
        });
    }

10.当前主页面上的UI结构

经过前面的编写,我们已经完成了新闻中心页面的大致编写,现在来回顾一下当前页面的结构:

在这里插入图片描述

11.网络缓存

在大部分应用中,即便是用户没有网络,也希望可以访问一些需要网络才能访问的功能,我们现在就来实现一下。

  1. 在util包下新建CacheUtil类,使用PreferenceShared来通过url将网上的json数据持久化到本地,代表网络缓存的工具类,代码如下:
package com.example.zhbj.util;

import android.content.Context;

/**
 * 网络缓存的工具类
 */
public class CacheUtil {

    /**
     * 写缓存
     * @param context 上下文对象
     * @param url 标识
     * @param json 数据,要保存到本地
     */
    public static void setCache(Context context,String url, String json){
        PrefUtils.putString(context,url,json);
    }

    /**
     * 读缓存
     * @param context 上下文对象
     * @param url 标识
     */
    public static String getCache(Context context,String url){
        String data = PrefUtils.getString(context, url, null);
        return data;
    }
}
  1. 修改NewsCenterPaper,修改getDataFromServer()方法,在读取到网络数据的时候将缓存写入到本地。并修改initData()方法,在每次切换到新闻中心页面时读取本地缓存,注意在读取时进行非空判断,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.base.BaseMenuDetailPaper;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.menudetail.InteractMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.NewsMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.PhotosMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.TopicMenuDetailPaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.example.zhbj.global.GlobalConstans;
import com.example.zhbj.util.CacheUtil;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

import java.util.ArrayList;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    /**
     * 存放四个菜单详情页对象的集合
     */
    private ArrayList<BaseMenuDetailPaper>  mPapers;

    /**
     * 从服务器上获取到的JSON数据
     */
    private NewsMenu newsMenu;

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        /*
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象
        */

        // 设置标题
        tvTitle.setText("新闻");

        String cache = CacheUtil.getCache(mActivity, GlobalConstans.CATEGORY_URL);
        if (!TextUtils.isEmpty(cache)){
            // 有缓存
            processData(cache);
        }else {
            // 无缓存,从服务器获取数据
            getDataFromServer();
        }

    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);

                        // 写缓存
                        CacheUtil.setCache(mActivity,GlobalConstans.CATEGORY_URL,result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        newsMenu = gson.fromJson(json, NewsMenu.class);

        // 找到侧边栏对象
        MainActivity mainUI = (MainActivity) mActivity;
        LeftMenuFragment fragment = mainUI.getLeftMenuFragment();
        fragment.setMenuData(newsMenu.data);

        // 网络请求成功之后,初始化四个菜单详情页
        mPapers = new ArrayList<>();
        mPapers.add(new NewsMenuDetailPaper(mActivity));
        mPapers.add(new TopicMenuDetailPaper(mActivity));
        mPapers.add(new PhotosMenuDetailPaper(mActivity));
        mPapers.add(new InteractMenuDetailPaper(mActivity));

        // 设置新闻菜单详情页为默认页面
        setMenuDetailPager(0);
    }

    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){
        BaseMenuDetailPaper paper = mPapers.get(position);

        // 清除之前帧布局显示的内容
        flContainer.removeAllViews();

        // 修改当前帧布局显示的内容
        flContainer.addView(paper.mRootView);

        // 初始化当前页面的数据
        paper.initData();

        // 修改标题栏
        tvTitle.setText(newsMenu.data.get(position).title);
    }
}
  1. 修改NewsCenterPaper,为了保证数据的实时性,优化代码,代码如下:
package com.example.zhbj.base.impl;

import android.app.Activity;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.TextView;

import com.example.zhbj.MainActivity;
import com.example.zhbj.base.BaseMenuDetailPaper;
import com.example.zhbj.base.BasePaper;
import com.example.zhbj.base.impl.menudetail.InteractMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.NewsMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.PhotosMenuDetailPaper;
import com.example.zhbj.base.impl.menudetail.TopicMenuDetailPaper;
import com.example.zhbj.domain.NewsMenu;
import com.example.zhbj.fragment.LeftMenuFragment;
import com.example.zhbj.global.GlobalConstans;
import com.example.zhbj.util.CacheUtil;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

import java.util.ArrayList;

/**
 * 新闻中心
 */
public class NewsCenterPaper extends BasePaper {

    /**
     * 存放四个菜单详情页对象的集合
     */
    private ArrayList<BaseMenuDetailPaper>  mPapers;

    /**
     * 从服务器上获取到的JSON数据
     */
    private NewsMenu newsMenu;

    public NewsCenterPaper(Activity activity) {
        super(activity);
    }

    @Override
    public void initData() {
        // 给空的帧布局动态添加布局对象
        /*
        TextView view = new TextView(mActivity);
        view.setTextSize(22);
        view.setTextColor(Color.RED);
        view.setGravity(Gravity.CENTER); // 居中显示
        view.setText("新闻中心");
        flContainer.addView(view); // 给帧布局添加对象
        */

        // 设置标题
        tvTitle.setText("新闻");

        String cache = CacheUtil.getCache(mActivity, GlobalConstans.CATEGORY_URL);
        if (!TextUtils.isEmpty(cache)) {
            // 有缓存
            processData(cache);
        }
        /*
        }else {
            // 无缓存,从服务器获取数据
            getDataFromServer();
        }
        */
        // 继续请求服务器数据,保证缓存更新
        getDataFromServer();

    }

    /**
     * 从服务器获取数据
     */
    private void getDataFromServer() {

        // Xutils
        HttpUtils utils = new HttpUtils();
        // 原生模拟器:10.0.2.2;Genymotion:10.0.3.2
        utils.send(HttpRequest.HttpMethod.GET, GlobalConstans.CATEGORY_URL,
                new RequestCallBack<String>() {

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = responseInfo.result;
                        System.out.println("服务器分类数据:" + result);
                        processData(result);

                        // 写缓存
                        CacheUtil.setCache(mActivity,GlobalConstans.CATEGORY_URL,result);
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                    }
                });
    }

    /**
     * 解析从服务器获取的JSON数据
     */
    private void processData(String json) {
        Gson gson = new Gson();
        // 通过json和对象类,来生成一个对象
        newsMenu = gson.fromJson(json, NewsMenu.class);

        // 找到侧边栏对象
        MainActivity mainUI = (MainActivity) mActivity;
        LeftMenuFragment fragment = mainUI.getLeftMenuFragment();
        fragment.setMenuData(newsMenu.data);

        // 网络请求成功之后,初始化四个菜单详情页
        mPapers = new ArrayList<>();
        mPapers.add(new NewsMenuDetailPaper(mActivity));
        mPapers.add(new TopicMenuDetailPaper(mActivity));
        mPapers.add(new PhotosMenuDetailPaper(mActivity));
        mPapers.add(new InteractMenuDetailPaper(mActivity));

        // 设置新闻菜单详情页为默认页面
        setMenuDetailPager(0);
    }

    /**
     * 设置新闻中心的详情页
     * @param position
     */
    public void setMenuDetailPager(int position){
        BaseMenuDetailPaper paper = mPapers.get(position);

        // 清除之前帧布局显示的内容
        flContainer.removeAllViews();

        // 修改当前帧布局显示的内容
        flContainer.addView(paper.mRootView);

        // 初始化当前页面的数据
        paper.initData();

        // 修改标题栏
        tvTitle.setText(newsMenu.data.get(position).title);
    }
}
发布了253 篇原创文章 · 获赞 52 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_41151659/article/details/104081934
今日推荐