• Diycode开源项目 SitesListFragment分析


    1.效果预览

    1.1.网站列表实际界面

      

    1.2.注意这个界面没有继承SimpleRefreshRecycleFragment

      前面的话题和新闻继承了SimpleRefreshRecyclerFragment

      但是网站的页面继承了第二等级的RefreshRecyclerFragment

      区别就在于:

        第三等级的SimpleRefreshRecyclerFragment具有快速回到顶部的功能。

      其实SitesListFragment也有快速回到顶部的功能,不过和前两个不太一样。

      因为布局的方式不一样,

      SitesListFragment要获取一个GridLayoutManager

      但是前两个要获取一个自定义的LinearLayoutManager


    2.SitesListFragment整体分析

    2.1.布局依旧是和前两个一样的

      

      这是RefreshRecyclerFragment中定义的布局

      所以可以知道布局是一样的

      那么RecyclerView是支持多列分布的。

    2.2.函数分布情况

      

      除了newInstance函数和convertData是自己新建的函数外,其他都是override基类中的方法的。

    2.3.SitesListFragment源代码

    /*
     * Copyright 2017 GcsSloop
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *    http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     * Last modified 2017-04-09 14:32:41
     *
     * GitHub:  https://github.com/GcsSloop
     * Website: http://www.gcssloop.com
     * Weibo:   http://weibo.com/GcsSloop
     */
    
    package com.gcssloop.diycode.fragment;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.RecyclerView;
    
    import com.gcssloop.diycode.fragment.base.RefreshRecyclerFragment;
    import com.gcssloop.diycode.fragment.bean.SiteItem;
    import com.gcssloop.diycode.fragment.bean.SitesItem;
    import com.gcssloop.diycode.fragment.provider.SiteProvider;
    import com.gcssloop.diycode.fragment.provider.SitesProvider;
    import com.gcssloop.diycode_sdk.api.sites.bean.Sites;
    import com.gcssloop.diycode_sdk.api.sites.event.GetSitesEvent;
    import com.gcssloop.diycode_sdk.log.Logger;
    import com.gcssloop.recyclerview.adapter.multitype.HeaderFooterAdapter;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 首页 sites 列表
     */
    public class SitesListFragment extends RefreshRecyclerFragment<Sites, GetSitesEvent> {
    
        public static SitesListFragment newInstance() {
            Bundle args = new Bundle();
            SitesListFragment fragment = new SitesListFragment();
            fragment.setArguments(args);
            return fragment;
        }
    
        @Override public void initData(HeaderFooterAdapter adapter) {
            setLoadMoreEnable(true);
            List<Serializable> sitesList = mDataCache.getSitesItems();
            if (sitesList != null) {
                Logger.e("sites : " + sitesList.size());
                mAdapter.addDatas(sitesList);
                setLoadMoreEnable(false);
            } else {
                loadMore();
            }
        }
    
        @Override
        protected void setAdapterRegister(Context context, RecyclerView recyclerView,
                                          HeaderFooterAdapter adapter) {
            mAdapter.register(SiteItem.class, new SiteProvider(getContext()));
            mAdapter.register(SitesItem.class, new SitesProvider(getContext()));
        }
    
        @NonNull @Override protected RecyclerView.LayoutManager getRecyclerViewLayoutManager() {
            GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
            layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return (mAdapter.getFullDatas().get(position) instanceof SiteItem) ? 1 : 2;
                }
            });
            return layoutManager;
        }
    
        @NonNull @Override protected String request(int offset, int limit) {
            return mDiycode.getSites();
        }
    
        @Override protected void onRefresh(GetSitesEvent event, HeaderFooterAdapter adapter) {
            toast("刷新成功");
            convertData(event.getBean());
        }
    
        @Override protected void onLoadMore(GetSitesEvent event, HeaderFooterAdapter adapter) {
            toast("加载成功");
            convertData(event.getBean());
        }
    
        @Override protected void onError(GetSitesEvent event, String postType) {
            toast("获取失败");
        }
    
        // 转换数据
        private void convertData(final List<Sites> sitesList) {
            ArrayList<Serializable> items = new ArrayList<>();
            for (Sites sites : sitesList) {
    
                items.add(new SitesItem(sites.getName()));
    
                for (Sites.Site site : sites.getSites()) {
                    items.add(new SiteItem(site.getName(), site.getUrl(), site.getAvatar_url()));
                }
    
                if (sites.getSites().size() % 2 == 1) {
                    items.add(new SiteItem("", "", ""));
                }
            }
    
            mAdapter.clearDatas();
            mAdapter.addDatas(items);
            mDataCache.saveSitesItems(items);
            setLoadMoreEnable(false);
        }
    }
    View Code


    3.SitesListFragment局部分析

    3.1.新建一个实例

      

      这个不解释了,args其实没有数据,可能是为了方便,直接copy的。

    3.2.初始化initData

      这是基类中最后执行的方法。

      

      这里的作用:判断缓存中有没有网站数据。如果有,直接加到adapter中,如果没有执行RefreshRecyclerFragment

            中的loadMore()方法,loadMore主要是进行request请求,然后确定请求状态数据等。

    3.3.注册数据类型

      

      这里和其他不一样,这里注册了两个类,所以了解一下这两个类。

      SiteItem==>

      

      然后是SitesItem==>

      

      SiteItem有:name,url,avater_url

      SitesItem有:name

      都是自定义的Bean类。

    3.4.获取布局管理器

      

      这里的布局采用了GridLayoutManager==>格子分布,包括两列。

      也许这里才是关键的布局设置。

    3.5.请求函数

      

      获取网站数据。

    3.6.刷新数据

      

      这里调用BaseFragment中的toast函数

      然后调用convertData函数

      

      终于理解了。这个items其实是所有的站点的集合。

      因为这个SitesListFragment分了几个大模块。

      每个模块中可能是奇数个,如果是奇数个,就添加一个空的接下去。

      其中每个模块也是用了一个for循环遍历了sites中的getSites。

      所以这个sitesList就是遍历模块的种类。

      然后这个sites.getSites就是遍历每一个模块中的站点。

      

    3.7. 加载更多

      

      同样调用了数据转换的函数。

    3.8.获取失败

        


    4.总结一下

    4.1.懂得这个SiteItem和SiteItems的区别,其实这是两个不同的类,看到实际的界面之后理解了。因为首先有多个模块。

      然后模块中是具体的某些站点,这个站点其实就是SiteItem包括了名字,url,头像,这个模块其实就是SiteItems

      仅仅展示一些名称就好,类别名称。

    4.2.这里的初始化数据要理解一下,这里首先从缓存中得到一个sitesList,其实这个sitesList就是所有的站点+模块类别,

      因为这两个类很相似,一个叫做SiteItem,一个叫做SitesItem,在注册数据类型的时候,应该就是如果数据对应

      的是SiteItem,采用某一种布局,然后如果数据对应是SitesItem,就采用另外一种布局。

    4.3.在关键函数convertData数据转换中,首先就变量模块个数,每个模块都加到一个ArrayList<Serializable>,很明

      显,SitesItem和SiteItem是不同类型的,但是都实现Serializable,所以都可以采用items.add的方式添加到这个

      集合中。值得注意的是,如果某个类别有奇数个,那么用一个空的填充到尾巴。

    4.4.然后是一个getRecyclerViewLayoutManager函数,因为这个SiteListFragment没有继承第三等级的封装类,所以

      要自己写一个获取布局管理器的函数。这里将布局分成了2部分了,然后调用了一个setSpanSizeLookup来判断

      应该执行那个布局。以后再详细了解。


    既然选择了,便不顾风雨兼程。Just follow yourself.
  • 相关阅读:
    (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
    (转)Elasticsearch分析聚合
    搜索引擎-倒排索引基础知识(摘自《这就是搜索引擎:核心技术详解》)
    Elasticsearch5.x Head插件安装
    Java开发规范总结
    (转)ElasticSearch Java Api-检索索引库
    QTGraphics-View拖拽以及鼠标指针操作
    Qt Graphics-View的打印功能实现
    Qt使用QPainter绘制矢量图并保存为svg文件
    QT制作一个位图画图板程序
  • 原文地址:https://www.cnblogs.com/Jason-Jan/p/7895946.html
Copyright © 2020-2023  润新知