如此抄袭Apps之OscHub(二)

来源:互联网 发布:免费书籍阅读软件 编辑:程序博客网 时间:2024/06/05 11:08

在上一篇博客中我们已经实现了OscHub最基本的框架,在接下来的几篇文章中我们来一起逐渐来充实其内容。这篇博客我们主要实现的内容主要有:

  • 综合Tab页面的两个Tabs的实现
  • 新闻列表数据的解析与展示

话不多说,走起~~~


综合Tab页总共包含了四个子Tabs,这里我们先简单实现资讯热点两个Tabs列表的展示。在原代码(开源中国Android客户端)中,这两个Tabs均是通过NewsFragment来展现内容的,而博客推荐则是用了BlogFragment实现,这个我下篇文章中会讲到。其实两类列表大同小异,相信聪明的你自己就能猜测到具体的实现方式了。

我们在上一篇博客里已经了解到,综合Tab本身是一个Fragment实体类,而其所包含的四个子Tabs同样是Fragment的实体类。这时候我们要注意的是,在添加子Tabs时,使用到的FramgentManager是通过方法getChildFragmentManager()得到,而不是调用getFragmentManager

与之前的实现方式类似,为了最大可能的共用代码,我们首先实现一个列表Fragment的基类BaseListFragment。该类是一个抽象类,要求子类必须实现其指定的抽象方法。在该类中实现了展示列表和请求数据的基本框架。类中采取了谷歌官方提供的下拉刷新列表类SwipeRefreshLayout和自定义的一个交互控件(主要用于数据加载中、数据加载失败、无网络等信息提示)。在该类中,我们暂时不实现加载更多的功能,后面我会用单独的一篇博客来介绍如何使用SwipeRefreshLayout实现下拉刷新、上拉加载更多的功能。这里我们只要把握整个数据加载、展示的流程就可以了,具体细节大家可以参考原代码了解。

BaseListFragment中还提供了数据请求和解析的对外接口和实现方法。数据的请求,我们使用第三方库android-async-http,而数据的解析,则使用了xstream库来解决。这里需要说明的是,使用Gradle来引入xstream时,Android Studio会报异常的错误,所以在工程中我直接使用了原代码中的jar包放入了libs中。

现在就让我们看看BaseListFragment的基本框架

  • 首先是基本的变量声明和依赖注入:
public static final String BUNDLE_KEY_CATALOG = "BUNDLE_KEY_CATALOG";    @Bind(R.id.swiperefreshlayout)    protected SwipeRefreshLayout mSwipeRefreshLayout;    @Bind(R.id.listview)    protected ListView mListView;    protected ListBaseAdapter<T> mAdapter;    @Bind(R.id.error_layout)    protected EmptyLayout mErrorLayout;    protected int mCurrentPage = 0;    protected int mCatalog = 1;    // 错误信息    protected Result mResult;    private ParserTask mParserTask;
  • 然后是几个关键方法的重写,包括了onCreategetLayoutIdonCreateViewonViewCreatedinitView等方法。
  • 在类中,有两个重要的成员变量不得不提,一个是AsyncHttpResponseHandler的实例,还一个是其嵌套类ParserTask的实例:
protected AsyncHttpResponseHandler mHandler = new AsyncHttpResponseHandler() {        @Override        public void onSuccess(int statusCode, Header[] headers,                byte[] responseBytes) {            if (isAdded()) {                executeParserTask(responseBytes);            }        }        @Override        public void onFailure(int arg0, Header[] arg1, byte[] arg2,                Throwable arg3) {        }    };    class ParserTask extends AsyncTask<Void, Void, String> {        private final byte[] reponseData;        private List<T> list;        public ParserTask(byte[] data) {            this.reponseData = data;        }        @Override        protected String doInBackground(Void... params) {            try {                ListEntity<T> data = parseList(new ByteArrayInputStream(                        reponseData));                list = data.getList();            } catch (Exception e) {            }            return null;        }        @Override        protected void onPostExecute(String result) {            super.onPostExecute(result);            executeOnLoadDataSuccess(list);            executeOnLoadFinish();        }    }
  • 其他几个方法主要是控制SwipeRefreshLayout的状态,请大家参照源码来理解。
  • 这个类目前提供的唯一抽象方法便是getListAdapter。这个很好理解。由于每个子类在显示数据上会略有不同,要求各个子类还实现自己的适配器是很正常的逻辑。即便如此,在原代码中,ListBaseAdapter还是实现了对刷新列表的控制,子类只需要重写getRealView方法就可以了。

以上我们简单介绍了列表基类BaseListFragment的实现,下面我们就来看看如何在子Tabs中使用ViewPager来展示多个Tabs。

打开我们的BaseViewPagerFragment类,加入对ViewPager和Tabs指示器的功能:

protected PagerSlidingTabStrip mTabStrip;    protected ViewPager mViewPager;    protected ViewPageFragmentAdapter mTabAdapter;    protected EmptyLayout mErrorLayout;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        return inflater.inflate(R.layout.base_viewpage_fragment, null);    }    @Override    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {        super.onViewCreated(view, savedInstanceState);        initView(view);    }    @Override    public void initView(View view) {        mTabStrip = (PagerSlidingTabStrip) view.findViewById(R.id.pager_tabstrip);        mViewPager = (ViewPager) view.findViewById(R.id.pager);        mErrorLayout = (EmptyLayout) view.findViewById(R.id.error_layout);        mTabAdapter = new ViewPageFragmentAdapter(getChildFragmentManager(), mTabStrip, mViewPager);        setScreenPageLimit();        onSetupTabAdapter(mTabAdapter);    }    protected void setScreenPageLimit() {    }    protected abstract void onSetupTabAdapter(ViewPageFragmentAdapter adapter);

有了基类BaseViewPagerFragment的支持,子类的实现就轻而易举了,比如NewsViewPagerFragment的实现:

public class NewsViewPagerFragment extends BaseViewPagerFragment implements OnTabReselectListener {    @Override    protected void onSetupTabAdapter(ViewPageFragmentAdapter adapter) {        String[] title = getResources().getStringArray(                R.array.news_viewpage_arrays);        adapter.addTab("news", title[0], NewsFragment.class,                getBundle(NewsList.CATALOG_ALL));        adapter.addTab("news_week", title[1], NewsFragment.class,                getBundle(NewsList.CATALOG_WEEK));    }    private Bundle getBundle(int newType) {        Bundle bundle = new Bundle();        bundle.putInt(BaseListFragment.BUNDLE_KEY_CATALOG, newType);        return bundle;    }    @Override    protected void setScreenPageLimit() {        mViewPager.setOffscreenPageLimit(3);    }    @Override    public void onTabReselect() {        try {            int currentIndex = mViewPager.getCurrentItem();            Fragment currentFragment = getChildFragmentManager().getFragments()                    .get(currentIndex);            if (currentFragment != null                    && currentFragment instanceof OnTabReselectListener) {                OnTabReselectListener listener = (OnTabReselectListener) currentFragment;                listener.onTabReselect();            }        } catch (NullPointerException e) {        }    }}

好了,我们这次的主要内容已经介绍完毕。大家可能觉得介绍的很粗糙。其实,大家看代码就会明白,我们自己在“抄袭”的过程中实际上已经去掉了原代码中我们暂时不关系的东西,而这些留下来的内容便是我们这次需要去学习和掌握的知识。从某种程度上来说,这又何尝不是一种对于原代码的解析呢?

下篇博客中,我们会来学习综合Tab中另外两个Tabs的实现,以及动弹Tab的内容。欢迎大家批评指正。

最后附上效果图:

效果图

源码请移步这里

Commit版本:3c20e4

0 0
原创粉丝点击