一.
如上图所示,MainActivity的两个部分LeftFragment和MainFragment,这两个部分结构搭建好了,布局也有了, MainFragment中的ViewPager要显示的13个页面控件虽然也有了,但是像首页中的ViewPager,TextView,ListView其他页面中的ImageView,TextView,ListView等控件中还没有真正的数据,这些数据我们要从网络上拿下来,拿过来的数据是json格式,我们要用Gson把这些数据解析出来。
还记得我们在BasePage页面创建了一个抽象方法initData()吗?各个子页面继承了BasePage,必须要实现这个方法,在这个方法里面各自从网络拿到自己的数据,然后再解析数据,把数据放到相应的控件上面。
那initData()方法是什么时候调用的呢?想想看,如果我们把initData()方法放在BasePage的构造方法中,那么MainFragment对象创建的时候会创建13个页面,这个时候会一下子调用13个页面的initData()方法,一下子把所有页面的数据都下载下来了。这个肯定不合适。那么什么时候调用呢?当然是切换到什么页面,调用该页面的initData()方法从网络加载数据。而切换页面的时候肯定会调用Adapter中的instantiateItem ()方法。在这个方法中调用13个页面的initData()方法。
我在网上找到一个知乎日报的数据接口,地址是https://github.com/izzyleung/ZhihuDailyPurify/wiki/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5-API-%E5%88%86%E6%9E%90,它返回的数据都是Json格式的。你们好好读一下接口文档,分析下怎么调用自己所需要的数据。
我们现在需要13个页面的数据,据分析,首页数据的URL: http://news-at.zhihu.com/api/4/news/latest。其他12个主题日报的URL:http://news-at.zhihu.com/api/4/theme/(主题日报的id),例如,http://news-at.zhihu.com/api/4/theme/13可以拿到日常心理学的数据,这里的13为日常心理学的id。
这个id我是通过http://news-at.zhihu.com/api/4/themes这个地址拿到,拿到之后放到HiJson这个软件里面,会把拿到的Json数据结构化,如下图所示:
所以我们看到用户推荐日报的id是12,那么拿到它的数据的url为http://news-at.zhihu.com/api/4/theme/12,其他主题日报的url只要改变一下id就可以了。
因为这12个主题日报所对应的id不会变,为了少访问一次网络,少解析一次数据,所以我把这些id拿出来,按菜单区ListView各个item(日常心理学,用户推荐日报,电影日报等)的顺序放在数组里面。如下图:
在MainFragment的ViewPager中的instantiateItem()方法中调用BasePage的initData()方法,如果位置是首页,传入空字符串。如果是其他12个页面,传入对应的id。
总结一下,首页的url和其他页面的url完全不一样,再加上我们前面说的首页的布局也和其他页面的布局不同,所以这里我们分为两个部分来处理。第一个部分当然是首页单独为一部分。首页页面继承BasePage实现它的initData()方法从网络拿到数据,解析后放到想要的控件上面。第二个部分是12个页面,它们布局一模一样,从网络拿到的数据结构也是一模一样,url也差不多,只是后面的id不一样。所以我们可以把这些一样的内容抽取出来,放在同一个类里面。我们将会创建ThemeDailyBasePage这个类,它继承于BasePage,实现initData()方法,在这个方法中也是从网络中拿到数据,解析后放到相应的控件上面。然后12页面分别继承于ThemeDailyBasePage这个类,12个页面相似的加载数据,为组件填充数据的逻辑都在ThemeDailyBasePage这个类中实现了。12页面中只需要改一下标题就可以了。
二.现在我们用代码来解释上述过程
1.MainFragment中,12个主题日报的id按顺序创建数组。在Adapter的instantiateItem()方法中调用BasePage的initData()方法,传入相应的id
public class MainFragment extends BaseFragment {
// 13个页面的集合
private List<BasePage> allPages = new ArrayList<BasePage>();
private MyViewPager mViewPager;
// 12个主题日报的id,例如日常心理学的id为13,用户推荐日报对应的id为12,
// 后面获取相应的主题日报的url为http://news-at.zhihu.com/api/4/theme/ + id
// 例如要拿到日常心理学日报的数据url为http://news-at.zhihu.com/api/4/theme/13
private String[] themeDailyNumber = { "13", "12", "3", "11", "4",
"5", "6", "10", "2", "7", "9", "8" };
private int selectedPosition = 0;
......
// 根据传进来的位置编号在13个页面之间切换
public void switchPage(int position){
// selectedPosition成员变量记录传进来的编号
this.selectedPosition = position;
// 这个方法会调用Adapter中的getView方法
mViewPager.setCurrentItem(position);
}
private class MyAdapter extends PagerAdapter{
@Override
public int getCount() {
// TODO自动生成的方法存根
return allPages.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO自动生成的方法存根
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Objectobject) {
// TODO自动生成的方法存根
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 根据position拿到相应的页面
BasePage selectedPage = allPages.get(position);
// 拿到相应页面的View,加到容器中
container.addView(selectedPage.getRoot());
// 在这里调用initData()方法加载13个页面的数据。
// 如果selectedPosition为0,则为首页
// 如果selectedPosition不为0,则是其他12个主题日报,把对应的id传进去
if (selectedPosition != 0) {
selectedPage.initData(themeDailyNumber[selectedPosition -1]);
}else {
selectedPage.initData("");
}
return selectedPage.getRoot();
}
}
}
2.首页实现initData()方法,在该方法中从网络中加载数据,解析数据,把数据放到相应的控件上(具体的后面再讲)
public class HomeBasePage extends BasePage {
public HomeBasePage(MainActivity mainActivity) {
super(mainActivity);
// TODO自动生成的构造函数存根
}
// themeDailyNumber参数是主题日报的的id,首页中不需要,可以忽略
@Override
public void initData(String themeDailyNumber) {
}
3. ThemeDailyBasePage实现initData()方法,在该方法中从网络中加载数据,解析数据,把数据放到相应的控件上(具体的后面再讲)
public class HomeBasePage extends BasePage {
public HomeBasePage(MainActivity mainActivity) {
super(mainActivity);
// TODO自动生成的构造函数存根
}
// themeDailyNumber参数是主题日报的的id,首页中不需要,可以忽略
@Override
public void initData(String themeDailyNumber) {
}