《笑话大全》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忽略它,因为他是广告插件,不做讲解。然后下面就是两个单选按钮,分别代表两个界面和两种不同的网络请求方式,他的效果是这样的:
在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,是本人第一个完整的项目,用于总结所学的知识点,如果有错误的地方希望各位大神能够指出,谢谢!
完整截图: