《笑话大全》APP代码详解4

《笑话大全》APP的最后一章,关于主页的Fragment,先看代码:

public class ContentFragment extends Fragment {
    //装载Fragment的View
    private View view;
    //主页面的RadioGroup和RadioButton
    private RadioGroup radioGroup;
    private RadioButton radioButton1,radioButton2;
    //主页上的ViewPager;
    private HomeViewPager homeViewPager;
    //装载ViewPager的两个View,也就是两个布局文件。
    private View view1,view2;
    //存储两个布局文件的List集合。
    private List list;
    //主页底栏下的RadioGroup。
    private RadioGroup rg;
    //主页的文字ListView;
    private MyListView  textList;
    //附页的ListView
    private MyListView twoTextList;
    //Json数据对象
    private ArrayList jokesDataList;
    private ArrayList twoJokesDataList;
    //ListView适配器
    private TextListAdapter listAdapter;
    //ListView附页适配器
    private TwoListAdapter twoListAdapter;
    //声明文字页下拉刷新控件
    private SwipeRefreshLayout swipeLayout;
    //声明附页下拉刷新控件
    private SwipeRefreshLayout twoSwipe;
    //API page页数字段值
    private int page=2;
    private int page2=2;
    private Result.Data data;
    private Result2.Data data2;
    private TimeStamp timeStamp=new TimeStamp();
    private String s;
    private String s1;

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        view=inflater.inflate(R.layout.fragment_content,null);
        homeViewPager=(HomeViewPager)view.findViewById(R.id.viewpager_home);
        rg=(RadioGroup)view.findViewById(R.id.radio_main);

        AdView adView=new AdView(getActivity(), AdSize.FIT_SCREEN);
        LinearLayout adLayout=(LinearLayout)view.findViewById(R.id.adLayout);
        adLayout.addView(adView);

        //初始化ViewPager的函数。
        initViewPagerData();
        initView();
        return view;
    }

    /**
     * 当加载更多数据时,就调用此方法
     * 请求成功后,在onSuccess()方法中调用processData()方法进行数据解析时,第二个参数传入的是true
     * 就会执行该方法中if语句中的else语句。
     */
    private void getMoreDataFromServer(){
        HttpUtils utils=new HttpUtils();
        //send就是发送请求。参数一代表获取数据。参数二是请求API的地址,
        utils.send(HttpRequest.HttpMethod.GET,URLList.CATEGORY_URL1+page+URLList.CATEGORY_URL2,
                    new RequestCallBack() {

                        //请求成功
                        @Override
                        public void onSuccess(ResponseInfo responseInfo) {
                            String result=responseInfo.result;
                            processData(result,true);
                        }

                        //请求失败
                        @Override
                        public void onFailure(HttpException e, String s) {
                            e.printStackTrace();
                            Toast.makeText(getActivity(),s,Toast.LENGTH_SHORT).show();
                        }



                    });

    }
    private void getMoreTwoFromServer(){
        s1 = timeStamp.getTimeStamp(8);
        if (s1!=null){
            HttpUtils utils=new HttpUtils();
            if (s1!=null){
                //send就是发送请求。参数一代表获取数据。参数二是请求API的地址,
                utils.send(HttpRequest.HttpMethod.GET,URLList.TWO_CATEGORY_URL1+page2+URLList.TWO_CATEGORY_URL2+s1
                        , new RequestCallBack() {

                            //请求成功
                            @Override
                            public void onSuccess(ResponseInfo responseInfo) {
                                String result=responseInfo.result;
                                processTwoData(result,true);
                            }

                            //请求失败
                            @Override
                            public void onFailure(HttpException e, String s) {
                                e.printStackTrace();
                                Toast.makeText(getActivity(),s,Toast.LENGTH_SHORT).show();
                            }



                        });
            }
        }



    }
    //此函数用于设置RadioButton的自定义图片的大小
    private void initView(){
        radioGroup = (RadioGroup)view.findViewById(R.id.radio_main);
        radioButton1 = (RadioButton)view.findViewById(R.id.radio_button1);
        radioButton2 = (RadioButton)view.findViewById(R.id.radio_button2);



        //定义底部标签图片大小
        Drawable jokeDrawable=getResources().getDrawable(R.drawable.tab_joke_selector,null);
        //第一0是距左右边距离,第二0是距上下边距离,第三长度,第四宽度
        jokeDrawable.setBounds(0,0,50,50);
        //设置到第二个参数意为将图片放上面,放入的参数位置不同,图片的摆放位置不同。也可以四个参数全部为null,当然这样的结果就是没有图片。
        radioButton1.setCompoundDrawables(null,jokeDrawable, null, null);

        Drawable photoDrawable= getResources().getDrawable(R.drawable.tab_photo_selector,null);
        photoDrawable.setBounds(0, 0,50,50);
        radioButton2.setCompoundDrawables(null,photoDrawable, null,null);


        //初始化底部标签
        radioGroup.check(R.id.radio_button1);// 默认勾选首页,初始化时候让首页默认勾选
    }
    //初始化主页ViewPager的数据
    private void initViewPagerData(){
        LayoutInflater layoutInflater=LayoutInflater.from(getContext());
        view1=layoutInflater.inflate(R.layout.viewpager_home1,null);
        view2=layoutInflater.inflate(R.layout.viewpager_home2,null);
        //实例化文字页SwipeRefreshLayout.(Google官方下拉刷新控件)
        swipeLayout=(SwipeRefreshLayout)view1.findViewById(R.id.swiperefresh_layout);
        //下拉监听器,刷新回调函数(一般用于更新UI)
        swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getDataFromServer();
                //设置刷新完成,进度圆圈圈停止转动。
                swipeLayout.setRefreshing(false);
            }
        });
        //设置刷新小圆圈的进度颜色,旋转一圈即随机更改颜色。
        swipeLayout.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);
        // 设置手指在屏幕下拉多少距离会触发下拉刷新,200差不多了。其实默认的距离也很合适。
        swipeLayout.setDistanceToTriggerSync(200);
        //设置刷新控件的大小,这是默认选项。
        swipeLayout.setSize(SwipeRefreshLayout.DEFAULT);
        //ListView在View1的布局文件中,就必须在该布局文件中寻找Id并实例化,否则会空指针异常。
        textList=(MyListView)view1.findViewById(R.id.home_list);
        textList.setOnRefreshListener(new MyListView.OnRefreshListener() {
            @Override
            public void onLoadMore() {
                getMoreDataFromServer();
                if (data!=null) {
                    page++;
                }else{
                    page=2;
                    Toast.makeText(getContext(),"没有更多数据!",Toast.LENGTH_SHORT).show();
                }
            }
        });

        //附页List实例化
        twoTextList=(MyListView)view2.findViewById(R.id.two_list);
        twoTextList.setOnRefreshListener(new MyListView.OnRefreshListener() {
            @Override
            public void onLoadMore() {
                getMoreTwoFromServer();
                if (data2!=null) {
                    page2++;
                }else{
                    page2=2;
                    Toast.makeText(getContext(),"没有更多数据!",Toast.LENGTH_SHORT).show();
                }
            }
        });
        //附页下拉刷新
        twoSwipe=(SwipeRefreshLayout)view2.findViewById(R.id.swiperefresh_layout2);
        twoSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getDataFromTwoServer();
               twoSwipe.setRefreshing(false);
            }
        });
        twoSwipe.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);

        list=new ArrayList<>();
        list.add(view1);
        list.add(view2);
        homeViewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return list.size();
            }

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

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                container.addView(list.get(position));
                return list.get(position);
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view==object;
            }
        });
        //设置RadioGroup的监听,点击到那个按钮时,ViewPager就跳转到哪个页面。
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            //第一个参数是当前的RadioGroup对象,第二个参数是当前被选中的RadioButton的ID。
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                //判断当前是哪个按钮被选中。
                switch (checkedId){
                    //“笑话”页面
                    case R.id.radio_button1:
                        /**setCurrentItem()方法是切换到指定的View。在ViewPager中,所有的子布局都是从0开始编号进行排序存储的。
                         * 该方法第一个参数就是要切换的View的编号(可以这么理解),第二个参数决定切换时是否带有动画,这里选择的是不带动画。
                         */
                        homeViewPager.setCurrentItem(0,false);
                        break;
                    //“趣图”页面
                    case R.id.radio_button2:
                        homeViewPager.setCurrentItem(1,false);
                        getDataFromTwoServer();
                        break;
                    default:
                        break;
                }

            }
        });

        //初始化文字信息方法
       getDataFromServer();
       //getDataFromTwoServer();
    }

    //利用xUtils框架请求数据。
    private void getDataFromServer(){
        HttpUtils utils=new HttpUtils();
        //send就是发送请求。参数一代表获取数据。参数二是请求API的地址,
        utils.send(HttpRequest.HttpMethod.GET,URLList.CATEGORY_URL1+1+URLList.CATEGORY_URL2,
                //请求的是什么内容,泛型就写入相对应的数据类型。
                new RequestCallBack() {
                    //请求成功
                    @Override
                    public void onSuccess(ResponseInfo responseInfo) {
                        String result=responseInfo.result;
                        processData(result,false);
                    }
                    //请求失败
                    @Override
                    public void onFailure(HttpException e, String s) {
                        e.printStackTrace();
                        Toast.makeText(getActivity(),s,Toast.LENGTH_SHORT).show();
                    }

                });

    }
    /**
     * processData()函数用于解析Json数据
     * 使用Gson框架解析数据
     * 该方法中第一个参数为服务器传回的数据源,第二个参数作为标记,用于将ListView的数据进行合并,表示更多数据
     * 当isMore为非状态时,也就是不是更多数据的状态时,数据正常显示
     * 否则的话,也就是加载了更多的数据时,将更多数据的Json对象重新创建,并追加到原来的ListView中,进行合并
     */

    private void processData(String json,boolean isMore){

            Gson gson = new Gson();
            /**
             * gson.fromJson()函数意思是将Json数据转换为JAVA对象。
             * Json数据中字段对应的内容就是JAVA对象中字段内所存储的内容。
             */
            JsonBean fromJson = gson.fromJson(json, JsonBean.class);

            if (!isMore){
                //定义Json数据对象。
                jokesDataList = fromJson.getResult().getData();

                listAdapter = new TextListAdapter();
                //当数据对象不为null时,也就是里面有数据时,设置适配器用于填充进ListView.
                if (jokesDataList!=null) {
                    textList.setAdapter(listAdapter);
                }

            }else{
                //加载了更多数据的时候,重新创建Json数据对象
                ArrayList moreJokesData=fromJson.getResult().getData();
                //追加到第一个数据集合中,进行合并
                jokesDataList.addAll(moreJokesData);
                //刷新ListView
                listAdapter.notifyDataSetChanged();
            }
    }

    //填充ListView的适配器。
    public class TextListAdapter extends BaseAdapter {
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
             ViewHolder viewHolder;
            if (convertView==null){
                convertView=View.inflate(getActivity(),R.layout.joke_list_item,null);
                viewHolder=new ViewHolder();
                viewHolder.contentText=(TextView)convertView.findViewById(R.id.content_text);
                viewHolder.timerText=(TextView)convertView.findViewById(R.id.timer_text);
                convertView.setTag(viewHolder);
            }else {
                viewHolder=(ViewHolder)convertView.getTag();
            }
            data = (Result.Data)getItem(position);
            viewHolder.contentText.setText("        "+ data.getContent());
            viewHolder.timerText.setText("更新时间:"+ data.getUpdatetime());
            return convertView;
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public Object getItem(int position) {
            return jokesDataList.get(position);
        }
        @Override
        public int getCount() {
            return jokesDataList.size();
        }

    }
    //请求附页数据
    private void getDataFromTwoServer(){
        s = timeStamp.getTimeStamp(8);
        HttpUtils utils = new HttpUtils();
            //send就是发送请求。参数一代表获取数据。参数二是请求API的地址,
            utils.send(HttpRequest.HttpMethod.GET, URLList.TWO_CATEGORY_URL1+1+URLList.TWO_CATEGORY_URL2+s
                    //请求的是什么内容,泛型就写入相对应的数据类型。
                    ,new RequestCallBack() {
                        //请求失败
                        @Override
                        public void onFailure(HttpException e, String s) {
                            e.printStackTrace();
                            Toast.makeText(getActivity(), s, Toast.LENGTH_SHORT).show();
                        }

                        //请求成功
                        @Override
                        public void onSuccess(ResponseInfo responseInfo) {
                            String result = responseInfo.result;
                            processTwoData(result, false);
                        }
                    });
        Log.d("TAG",s);


    }
    private void processTwoData(String json,boolean isMore){
        Gson gson = new Gson();
        /**
         * gson.fromJson()函数意思是将Json数据转换为JAVA对象。
         * Json数据中字段对应的内容就是JAVA对象中字段内所存储的内容。
         */
        TwoJsonBean fromJson = gson.fromJson(json, TwoJsonBean.class);

            if (!isMore) {
                //定义Json数据对象。
                twoJokesDataList = fromJson.getResult().getData();
                twoListAdapter = new TwoListAdapter();

                //当数据对象不为null时,也就是里面有数据时,设置适配器用于填充进ListView.
                if (twoJokesDataList != null) {
                    twoTextList.setAdapter(twoListAdapter);
                }
            }else {
                //加载了更多数据的时候,重新创建Json数据对象
                ArrayList moreTwoData=fromJson.getResult().getData();
                //追加到第一个数据集合中,进行合并
                twoJokesDataList.addAll(moreTwoData);
                //刷新ListView
                twoListAdapter.notifyDataSetChanged();
            }

    }
    public class TwoListAdapter extends BaseAdapter {
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView==null){
                convertView=View.inflate(getActivity(),R.layout.jokes_list_item,null);
                holder=new ViewHolder();
                holder.contentText=(TextView)convertView.findViewById(R.id.two_content_text);
                holder.timerText=(TextView)convertView.findViewById(R.id.two_timer_text);
                convertView.setTag(holder);
            }else {
                holder=(ViewHolder)convertView.getTag();
            }
            data2 = (Result2.Data)getItem(position);
            holder.contentText.setText("        "+ data2.getContent());
            holder.timerText.setText("更新时间:"+ data2.getUpdatetime());

            return convertView;
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public Object getItem(int position) {
            return twoJokesDataList.get(position);
        }
        @Override
        public int getCount() {
            return twoJokesDataList.size();
        }

    }
}
代码有点长,我们一条一条的捋,先看onCreateView()函数里面加载的布局文件,是fragment_content,打开这个布局文件,看看它的布局是什么样子:


    

    
    
    
    

        
        
    

这是一个线性布局,上面引用的title_bar是标题栏,下面ViewPager就是要显示的笑话内容,下面的LinearLayout忽略它,因为他是广告插件,不做讲解。然后下面就是两个单选按钮,分别代表两个界面和两种不同的网络请求方式,他的效果是这样的:

《笑话大全》APP代码详解4_第1张图片

在ContentFragment加载完布局文件后,便实例化主页的ViewPager和RadioGroup:

homeViewPager=(HomeViewPager)view.findViewById(R.id.viewpager_home);
        rg=(RadioGroup)view.findViewById(R.id.radio_main);
紧接着是实例化广告插件,这里同样忽略它,只关注两个初始化数据的函数即可,也就是initViewPagerData()和initView()两个函数,先看initViewPagerData():

 //初始化主页ViewPager的数据
    private void initViewPagerData(){
        LayoutInflater layoutInflater=LayoutInflater.from(getContext());
        view1=layoutInflater.inflate(R.layout.viewpager_home1,null);
        view2=layoutInflater.inflate(R.layout.viewpager_home2,null);
        //实例化文字页SwipeRefreshLayout.(Google官方下拉刷新控件)
        swipeLayout=(SwipeRefreshLayout)view1.findViewById(R.id.swiperefresh_layout);
        //下拉监听器,刷新回调函数(一般用于更新UI)
        swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getDataFromServer();
                //设置刷新完成,进度圆圈圈停止转动。
                swipeLayout.setRefreshing(false);
            }
        });
        //设置刷新小圆圈的进度颜色,旋转一圈即随机更改颜色。
        swipeLayout.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);
        // 设置手指在屏幕下拉多少距离会触发下拉刷新,200差不多了。其实默认的距离也很合适。
        swipeLayout.setDistanceToTriggerSync(200);
        //设置刷新控件的大小,这是默认选项。
        swipeLayout.setSize(SwipeRefreshLayout.DEFAULT);
        //ListView在View1的布局文件中,就必须在该布局文件中寻找Id并实例化,否则会空指针异常。
        textList=(MyListView)view1.findViewById(R.id.home_list);
        textList.setOnRefreshListener(new MyListView.OnRefreshListener() {
            @Override
            public void onLoadMore() {
                getMoreDataFromServer();
                if (data!=null) {
                    page++;
                }else{
                    page=2;
                    Toast.makeText(getContext(),"没有更多数据!",Toast.LENGTH_SHORT).show();
                }
            }
        });

        //附页List实例化
        twoTextList=(MyListView)view2.findViewById(R.id.two_list);
        twoTextList.setOnRefreshListener(new MyListView.OnRefreshListener() {
            @Override
            public void onLoadMore() {
                getMoreTwoFromServer();
                if (data2!=null) {
                    page2++;
                }else{
                    page2=2;
                    Toast.makeText(getContext(),"没有更多数据!",Toast.LENGTH_SHORT).show();
                }
            }
        });
        //附页下拉刷新
        twoSwipe=(SwipeRefreshLayout)view2.findViewById(R.id.swiperefresh_layout2);
        twoSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getDataFromTwoServer();
               twoSwipe.setRefreshing(false);
            }
        });
        twoSwipe.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);

        list=new ArrayList<>();
        list.add(view1);
        list.add(view2);
        homeViewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return list.size();
            }

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

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                container.addView(list.get(position));
                return list.get(position);
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view==object;
            }
        });
        //设置RadioGroup的监听,点击到那个按钮时,ViewPager就跳转到哪个页面。
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            //第一个参数是当前的RadioGroup对象,第二个参数是当前被选中的RadioButton的ID。
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                //判断当前是哪个按钮被选中。
                switch (checkedId){
                    //“笑话”页面
                    case R.id.radio_button1:
                        /**setCurrentItem()方法是切换到指定的View。在ViewPager中,所有的子布局都是从0开始编号进行排序存储的。
                         * 该方法第一个参数就是要切换的View的编号(可以这么理解),第二个参数决定切换时是否带有动画,这里选择的是不带动画。
                         */
                        homeViewPager.setCurrentItem(0,false);
                        break;
                    //“趣图”页面
                    case R.id.radio_button2:
                        homeViewPager.setCurrentItem(1,false);
                        getDataFromTwoServer();
                        break;
                    default:
                        break;
                }

            }
        });

        //初始化文字信息方法
       getDataFromServer();
       //getDataFromTwoServer();
    }
可以看到,在initViewPagerData()函数中,首先装载两个填充ViewPager的布局文件,分别是viewpager_home1和viewpager_home2,然后实例化两个布局文件中的SwipeRefreshLayout,也就是官方的下拉刷新控件,并对它的一些常用属性进行了设置。然后是实例化布局文件中自定义的ListView,并设置了监听事件,还有RadioButton的点击事件。我们先看viewpager_home1中的布局文件代码:


    
    
        
    


很简单,就是帧布局中添加了下拉刷新控件,控件内是一个自定义的ListView,viewpager_home2中的代码和它是一样的,这里不再给出。我们看看自定义ListView中的代码是怎样的:

/**
  * 自定义ListView实现下拉刷新,上拉加载
  * 继承自ListView,实现自AbsListView.OnScrollListener(listView滑动监听)
  * */
public class MyListView extends ListView implements AbsListView.OnScrollListener {
    //尾布局
    private View mFooterView;
    //尾布局高度
    private int mFooterViewHeight;
    //当前显示的最后一个Item的角标值
    private int lastItem;
    //上拉加载中避免重复加载的标记
    private boolean isLoadMore;

     /**
      * 构造函数最好三个都写上,说不定会用得上。
      * */
     public MyListView(Context context) {
         super(context);
         initFooterView();
     }
     public MyListView(Context context, AttributeSet attrs) {
         super(context, attrs);
         initFooterView();
     }

     public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         initFooterView();
     }
     /**
      * 初始化尾布局
      */
     private void initFooterView(){
         
         //实例化尾布局,尾布局是自定义的listview_down文件
         mFooterView = View.inflate(getContext(), R.layout.listview_down,null);
         //将尾布局追加到ListView中
         this.addFooterView(mFooterView);
         //调用尾布局的measure()函数进行测量
         mFooterView.measure(0,0);
         //测量完毕后再调用getMeasuredHeight()获取测量到的高度,并赋值给mHeaderViewHeight
         mFooterViewHeight = mFooterView.getMeasuredHeight();
         //用setPadding()进行设置隐藏,四个参数依次是左,上,右,下。
         mFooterView.setPadding(0,-mFooterViewHeight,0,0);
         //设置滑动监听
         this.setOnScrollListener(this);
     }

    /**
     * 滑动监听必须重写的两个回调函数
     * onScroll是滑动过程回调,就是在滑动的过程中不断调用该函数
     * onScrollStateChanged是滑动状态发生改变时的回调
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if(scrollState==SCROLL_STATE_IDLE){//空闲状态
            //获取最后一个Item的位置,
            lastItem = getLastVisiblePosition();
            //判断是否到达ListView的最底部,如果是最底部并且没有正在加载更多
            if (lastItem==getCount()-1&&!isLoadMore){
                Log.d("TAG","加载更多...");
                //显示尾布局
                mFooterView.setPadding(0,0,0,0);
                //将尾布局显示在最后一个Item上,尾布局就会直接展示在ListView的最后一个Item上,无需手动滑动
                setSelection(getCount()-1);
                //通知主界面加载下一页数据
                if (mListener!=null){
                    mListener.onLoadMore();
                }
            }
        }
    }
    /**
     * 1.下拉刷新,上拉加载的回调接口
     */
    public interface OnRefreshListener{

        //上拉加载
        public void onLoadMore();
    }
    /**
     * 2.定义成员变量,接收监听对象
     */
    private OnRefreshListener mListener;
    /**
     * 3.暴露接口,设置监听
     */
    public void setOnRefreshListener(OnRefreshListener listener){
        mListener=listener;
    }
}
代码的注释中写的很清楚,由于下拉刷新控件我们用的是官方的控件,所以在自定义的ListView中只需要自定义上拉加载即可。至于尾布局的布局样式,它的代码如下所示:


    
    
    
介绍完了自定义的ListView,我们回过头来接着看initViewPager(),当下拉刷新控件和自定义的ListView实例化了之后,就应该为它设置监听事件了,不管是下拉刷新还是上拉加载,都会涉及到的就是数据更新,本程序是通过网络获取数据,所以理所当然的更新的数据就是网络数据,我们先看看两个刷新控件的监听代码。

先是下拉刷新:

//下拉监听器,刷新回调函数(一般用于更新UI)
        swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getDataFromServer();
                //设置刷新完成,进度圆圈圈停止转动。
                swipeLayout.setRefreshing(false);
            }
        });
然后是上拉加载:

//上拉加载监听
        textList.setOnRefreshListener(new MyListView.OnRefreshListener() {
            @Override
            public void onLoadMore() {
                getMoreDataFromServer();
                if (data!=null) {
                    page++;
                }else{
                    page=2;
                    Toast.makeText(getContext(),"没有更多数据!",Toast.LENGTH_SHORT).show();
                }
            }
        });
上拉加载的监听回调是我们在自定义ListView中自定义的一个接口,不理解的可以回看MyListView的代码。

两个刷新控件的监听调用的方法getDataFromServer()和getMoreDataFromServer()都是请求网络数据的,里面的代码都差不多,只是请求的地址有了些差别,我们只看getDataFromServer()函数就好:

//利用xUtils框架请求数据。
    private void getDataFromServer(){
        HttpUtils utils=new HttpUtils();
        //send就是发送请求。参数一代表获取数据。参数二是请求API的地址,
        utils.send(HttpRequest.HttpMethod.GET,URLList.CATEGORY_URL1+1+URLList.CATEGORY_URL2,
                //请求的是什么内容,泛型就写入相对应的数据类型。
                new RequestCallBack() {
                    //请求成功
                    @Override
                    public void onSuccess(ResponseInfo responseInfo) {
                        String result=responseInfo.result;
                        processData(result,false);
                    }
                    //请求失败
                    @Override
                    public void onFailure(HttpException e, String s) {
                        e.printStackTrace();
                        Toast.makeText(getActivity(),s,Toast.LENGTH_SHORT).show();
                    }

                });

    }
请求数据我的是第三方框架Xutils,请求成功后调用了processData()方法用于解析数据,下面是它的代码:

/**
     * processData()函数用于解析Json数据
     * 使用Gson框架解析数据
     * 该方法中第一个参数为服务器传回的数据源,第二个参数作为标记,用于将ListView的数据进行合并,表示更多数据
     * 当isMore为非状态时,也就是不是更多数据的状态时,数据正常显示
     * 否则的话,也就是加载了更多的数据时,将更多数据的Json对象重新创建,并追加到原来的ListView中,进行合并
     */

    private void processData(String json,boolean isMore){

            Gson gson = new Gson();
            /**
             * gson.fromJson()函数意思是将Json数据转换为JAVA对象。
             * Json数据中字段对应的内容就是JAVA对象中字段内所存储的内容。
             */
            JsonBean fromJson = gson.fromJson(json, JsonBean.class);

            if (!isMore){
                //定义Json数据对象。
                jokesDataList = fromJson.getResult().getData();

                listAdapter = new TextListAdapter();
                //当数据对象不为null时,也就是里面有数据时,设置适配器用于填充进ListView.
                if (jokesDataList!=null) {
                    textList.setAdapter(listAdapter);
                }

            }else{
                //加载了更多数据的时候,重新创建Json数据对象
                ArrayList moreJokesData=fromJson.getResult().getData();
                //追加到第一个数据集合中,进行合并
                jokesDataList.addAll(moreJokesData);
                //刷新ListView
                listAdapter.notifyDataSetChanged();
            }
    }
解析数据用的是Google官方的Gson,使用Gson解析数据时需要写一个Bean类,代码如下:

/**
 * Gson解析需要的数据类
 * 数据类的创建原则:逢{}创建对象,逢[]创建集合(一般情况下使用ArrayList)
 * 所有字段名称必须要和Json返回的字段一致。
 */
public class JsonBean {
    private Result result;
    public void setResult(Result result){
        this.result=result;
    }
    public Result getResult(){
        return result;
    }

}
public class Result {
    private ArrayList data;
    public void  setData(ArrayList data){
        this.data=data;
    }
    public ArrayList getData(){
        return data;
    }

    public class Data{
        private String content;
        private String updatetime;
        public void setContent(String content){
            this.content=content;
        }
        public String getContent(){
            return content;
        }
        public void setUpdatetime(String updatetime){
            this.updatetime=updatetime;
        }
        public String getUpdatetime(){
            return updatetime;
        }


    }


}
请求完数据之后就需要为ListView设置适配器,适配器代码如下:

//填充ListView的适配器。
    public class TextListAdapter extends BaseAdapter {
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
             ViewHolder viewHolder;
            if (convertView==null){
                convertView=View.inflate(getActivity(),R.layout.joke_list_item,null);
                viewHolder=new ViewHolder();
                viewHolder.contentText=(TextView)convertView.findViewById(R.id.content_text);
                viewHolder.timerText=(TextView)convertView.findViewById(R.id.timer_text);
                convertView.setTag(viewHolder);
            }else {
                viewHolder=(ViewHolder)convertView.getTag();
            }
            data = (Result.Data)getItem(position);
            viewHolder.contentText.setText("        "+ data.getContent());
            viewHolder.timerText.setText("更新时间:"+ data.getUpdatetime());
            return convertView;
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public Object getItem(int position) {
            return jokesDataList.get(position);
        }
        @Override
        public int getCount() {
            return jokesDataList.size();
        }

    }
里面涉及的类ViewHolder代码如下:

public class ViewHolder {
    public TextView contentText;
    public TextView timerText;
}
这样就完成了一次完整的网络请求。至于initViewPagerData()方法中的其他内容比如设置适配器和RadioButton点击事件监听,都很好理解,不再赘述。

现在看最后一部分initView()函数,代码少,容易理解:

//此函数用于设置RadioButton的自定义图片的大小
    private void initView(){
        radioGroup = (RadioGroup)view.findViewById(R.id.radio_main);
        radioButton1 = (RadioButton)view.findViewById(R.id.radio_button1);
        radioButton2 = (RadioButton)view.findViewById(R.id.radio_button2);



        //定义底部标签图片大小
        Drawable jokeDrawable=getResources().getDrawable(R.drawable.tab_joke_selector,null);
        //第一0是距左右边距离,第二0是距上下边距离,第三长度,第四宽度
        jokeDrawable.setBounds(0,0,50,50);
        //设置到第二个参数意为将图片放上面,放入的参数位置不同,图片的摆放位置不同。也可以四个参数全部为null,当然这样的结果就是没有图片。
        radioButton1.setCompoundDrawables(null,jokeDrawable, null, null);

        Drawable photoDrawable= getResources().getDrawable(R.drawable.tab_photo_selector,null);
        photoDrawable.setBounds(0, 0,50,50);
        radioButton2.setCompoundDrawables(null,photoDrawable, null,null);


        //初始化底部标签
        radioGroup.check(R.id.radio_button1);// 默认勾选首页,初始化时候让首页默认勾选
    }
注释中都写得很明白了,不再描述。

以上就是整个《笑话大全》APP的全部内容,这是一个很简单的APP,是本人第一个完整的项目,用于总结所学的知识点,如果有错误的地方希望各位大神能够指出,谢谢!


完整截图:

《笑话大全》APP代码详解4_第2张图片















你可能感兴趣的:(《笑话大全》)