1.使用Fragment搭建ui框架java
参考分析图android
1.1,Fragment生命周期面试
Is added(被添加以后)数据库
>>onAttach()>>onCreate()>>onCreateView()//建立布局>>onActivityCreated();//当activity建立好后(onCreate()执行完了以后)>>onStart()>>onResume()>>onPause()>>onStop()>>onDestory()json
1.2 建立一个Fragment的基类:参考名baseFragment(用v4保持版本兼容)数组
onCreate()//Fragment建立缓存
能够拿到这个Fragment所在的Activity对象tomcat
mActivity = getActivity();//成员变量通常加m性能优化
onCreateView()//初始化Fragment的布局服务器
返回的View就是Fragment对应的布局
但由于这个类是基类,因此不该该直接返回View
建立一个抽象方法让子类去实现,传入View并返回它
而后在onCreateView()中返回这个View便可
onActivityCreate()//fragment所依赖的acitivity的onCreate()方法执行完毕
能够用来初始化数据
一样写一个抽象方法,让子类实现,在这个方法里重写数据
1.3 建立两个子Fragment
①LeftMenuFragment的建立,继承基类,重写抽象的方法
可是在这里View.inflate()中,不能直接用this,由于Fragment是不继承上下文的,可是能够经过基类中获取的mActivity当作上下文传入
②ContentFragment的建立,步骤基本上同样
重写该重写的方法,返回对应的布局文件
1.4,在主界面的侧边栏和主菜单中,设置的布局文件清空(通常根节点用FrameLayout,干净)
在主界面的activity中,建立一个方法用来初始化Fragment
①拿到Fragment管理器>>
fm = getSupportFragmentManager()//兼容低版本的管理器
transaction = fm.beginTransaction();//开始事务
Transaction.replace(id,fragment)//id,给fragment提供的位置,fragment对象
若是参数异常就写个配置文件,名称与jar包一致(包含后缀名.properties)
内容为src=XXXX//源码的路径(在sdk/extras/android/xxx下 v4包的源码)
而后重启Eclipse便可
//两个Fragment能够一块儿替换
Transaction.commit()//提交事务
在Activity的onCreate()时调用
Transaction.Replasc()也有三个参数的,tag(String)第三个参数,之后找起来会比较方便
fm.findFragmentByTag(String tag)//经过Fragment管理器找到标记获取Fragment的对象.
2,主页面
2.1 主页面分析:从上至下(先不看内容填充)
上面是一个Viewpager
下面是一个RadioGroup + RadioButton
2.2 在ContentFragment中,搭建ui框架
2.2.1底部导航栏
RadioButton中 能够设置属性Button = @null//去掉能够被选中的小圆框
图片是经过drawableTop设置出来的
RadioButton背景设置全透明(由于有的手机上会有显示问题)
一样的,要设置状态选择器(选中的(state_checked)状态选择器)
记得要设置ID,不设置ID的话,所有都会被选中
默认设置首页被选中
2.2.2 ViewPager显示
①界面分析:
每个ViewPager页面都有共同的地方,
因此抽取一个布局基类base_pager
抽取一个标题的布局title_bar
在base_pager 中include导入这个布局
② 建立一个类(base包下)(单纯的类,什么都不继承)
BasePager表示ViewPager每个页面的基类
这个类表明五个标签页的基本类
建立方法:initView()//初始化布局,在构造中把Activity传进来便可
在这里把布局View找到,找到中间关心的控件
//返回这个布局对应的View便可,在构造中把这个View用成员变量记录下来
initData()//初始化数据
③建立实现类(impl包):
建立一个首页类继承base_pager类
重写的初始化数据方法中,new一个TextView(根据页面内容来,这里首页内容就只是一个TextView,因此只要new 一个TextView就能够了)
拿到空的帧布局对象(在Base_pager已经找到它了,能够以直接使用)
而后依次把其它几个标签页的建立出来(这里先不用填充数据)
3.填充标签页,禁用ViewPager的滑动事件
3.1 建立ViewPager适配器
3.2 初始化5个标签页
建立一个集合保存五个BasePager对象
PagerAdapter中instantiateItem()初始化一个View对象的时候
经过BasePager.mRootView获取到这个标签页对应的View对象,返回它
记得调用一下initData()让它生效
而后添加到ViewPager上面
额外:右击方法名,Open Call Hierachy能够看到调用的层级结构
3.3 禁用ViewPager的滑动换页(自定义一个ViewPager)参考:noScrollViewPager
重写一下onTouchEvent(event)直接返回true便可
由于google的工程师就是在触摸事件里让页面滑动的,因此返回true就能够了
3.4 点击标签切换页面&&性能优化
①拿到RadioGroup对象,设置切换监听器
②经过重写的方法里checkedId对应的选项,判断是哪个标签卡被选中了.
mViewPager.setCurrentItem(对应的索引就能够了,是否要平缓滑动效果(flase));
一个参数的就默认带有动画效果了
③ViewPager会提早加载下一个标签,在这里是没有必要预加载的.
ViewPager原生的方法修改起来很麻烦,因此在初始化数据的时候,不要直接调用initData()方法,由于初始化数据再有些标签卡中很耗时间
解决方式:设置ViewPager的页面监听,或在RadioButton中里面写
这里用ViewPager的页面监听来写,代码更简练一些?
在监听方法中,经过页面被选中的方法,参数Position来初始化数据
额外:进入界面的时候没有数据
在接入界面的时候加载上默认的数据
4,侧边栏的开启和禁用(在中间三个选项卡能够划出来侧边栏,第一个和最后一个标签没有侧边栏,这个根据状况来的)
4.1 隐藏侧边栏的按钮,在每个标签的实现类中,隐藏对应的按钮
4.2 当第一个页面和最后一个页面被选中的时候
在ViewPager的监听器中,当选中的position为第一个或最后一个的时候
禁用掉侧边栏
获取侧边栏对象
在ContentFragment中经过mActivity(SlidingMenuFragmentActivity)强转拿到
而后获取到侧边栏对象
设置滑动模式
SlidingMenu.setTouchMode(SlidingMenu.TOUCHMODE_NONE);//设置模式
5,新闻中心页面的开发
①新闻中心的数据都是网络传递过来的,包括侧边栏的内容也是解析网络数据获得的(使用服务器数据,把zhbj的文件夹丢到tomcat服务器的root下访问)
访问地址:服务器//zhbj/categories.json
工具:HiJson,把JSON串拷贝进来,能够格式化JSON字符串,方便阅读
解析JSON串[]表明JSON数组,{}表明JSON对象
有的JSON串最后会有retcode 表示这个JSON串是否获取成功
②使用XUtils请求数据
在须要请求服务器的标签类中initData()中请求网络
XUtils开源框架,四大模块
DBUtils,ViewUtils,HttpUtils,BitMapUtils(这里会用到后面三个模块)
6,Xutils使用
获取Xutils对象
HttpUtils utils = new HttpUtils();
Utils.send(HttpMethod.GET,url(不写死,写到一个类中),new RequestCallBackXX())
GlobalConstans类下
Public static final String SERVER_URL=”服务器主域名”
http://10.0.2.2(模拟器访问本机ip):8080/zhbj
Public static final String categories_URL=SERVER_URL + ”/cetgories.json”;//类别
在回调方法中,
请求成功的方法,获取结果response.result.
请求失败的方法参数error,msg
error.printStackTrace()//打印错误信息
msg String错误信息
7,使用Gson解析Json
Gson:google为了提升json解析效率搞出来的玩意(jar包)
Gson gson = new Gson();
gson.fromjson(String,clazz);//clazz是保存服务器数据的javaBean
建立一个JSON封装类(照着JSON串来写)
遇到大括号,就是一个对象,遇到中括号就是一个集合
最外层的大对象就
public int retcode;
Public ArrayList<Integer> extend //由于下面是一堆数据,通常用集合装下来
Public ArrayList data//只要是中括号,大部分状况下能够用集合表示
遇到大括号,在这个类中建立一个类,表示这个对象的内容
若是是单个的字段(用不上的不用解析)直接建立成员变量就行
Public int id ;
若是又是一个大括号,再建立一个平行的内部类
依次建立下去便可
使用JSON解析时,对象书写技巧:
逢{}建立对象,逢[]建立和,全部名称要和JSON字段高度一致(类名无所谓)
建立完毕后
gson.fromJson(json.clazz)//返回的就是这个clazz 对象
8,网络缓存
原理:将JSON数据做为缓存的内容,标示为:URL路径
缓存的东西就是JSON字符串.因此要保持URL与 JSON串相互对应的关系
①写一个工具类 CacheUtils
应该有两个方法,
写缓存setCache(String url,String json,Context,context)
以url为key,以json为value,保存在本地
这里保存在sp中比较方便
读缓存getCache(String url);//经过sp读到缓存内容,返回缓存便可(默认为null)
②使用方式:
须要请求数据的标签,先判断有没有缓存(是否为null)
若是有的话,就直接解析数据,不然就访问网络,获取数据
写缓存的位置,在请求完数据以后写入
细节1:URL可能不是一直对应这个JSON串
解决1:给缓存设置有效期(一个礼拜或一天,必须刷新一次)
解决2:读缓存的时候(读取完了缓存,调用一下解析数据的方法),不论是否有缓存都请求一次服务器(不用担忧新旧缓存的问题,这样既有老的数据,可让用户先看到一些数据,用户体验好一些,而后网络加载完以后更新,用户耐心更好)
细节2:储存在sp中会致使sp可读性太差
解决1:数据库
解决2:用文件储存
以URL为文件名,以JSON为文件内容,读缓存的时候就直接查找有没有缓存文件便可.
可是URL有可能有特殊字符,因此能够用MD5转换一下,就能够做为文件名
注意:网络缓存通常就是缓存的JSON,面试问到也就是缓存JSON
若是URL后面带参数,也是一样要带参数的(路径拼接便可)
9,设置新闻中心的侧边栏数据
重点是如何拿到侧边栏对象
在这里MainActivity其实已经获取到了,就是mActivity;
在解析数据的方法里
经过mActivity强转获得MainActivity
在MainActivity中,建立一个方法,找到侧边栏对象
FragmentManager .findFragmentByTag()//经过前面设置的标签获取Fragment对象
而后在新闻中心的Pager类中,拿到侧边栏对象
在侧边栏Fragment类中,建立一个方法设置数据,在新闻中心类中,把须要传递的数据经过参数传递过去(JSON串中的新闻中心数据)
这里的侧边栏其实就是一个ListView
把传递过来的新闻中心数据解析出来,传递到ListView上
这里使用ViewUtils模块,使用注解的方法替代fbc和onClick;
①注入View和事件
ViewUtils.inject(this,view);
②建立须要替代的成员变量:
@ViewInject(id)
Private ListView mListView;
ViewUtils底层其实也是fbc,不过是经过注解的方式封装好了.
③建立适配器,设置数据
getItem()能够直接返回一个与position相关的对象(这里能够把它的返回值对象改了)
getItemId()能够直接把position返回
getView()方法
须要再写一个item的布局文件
这里的侧边栏条目状态选择器,经过enabled是否可用来设置状态
(由于LIstView不像 RadioButton,有选中和不被选中的选择)
定义一个成员变量记录被点击(也就是被选中的条目)就让它设置可用,不然设置不可用
④设置ListView点击事件监听器
更新被点击的条目,而后刷新适配器(由于侧边栏条目比较少,因此不影响太多效率)
⑤优化:点击了其它条目,应该收集侧边栏
建立一个方法,toggle()//开关的方法
经过mainActivity(mainUi)拿到侧边栏对象
slidingMenu.toggle()//调用以后会根据当前状态自动判断是否显示
额外:设置左上角的按钮事件
10,点击侧边栏切换菜单详情页
侧边栏点击以后,要修改Fragment里面的内容
搭建详情页Ui框架
①抽取一个菜单详情页的基类BaseMenuDetailPager
一样的,在构造方法里获取到mActivity.调用initView()方法获得返回的View
这个基类的initView()由于每一个孩子的都不同,因此让子类去强制实现
initData()//这个方法能够强制,也能够不强制
而后把四个详情页都建立出来
这里为了观察方便,先返回四个简单的TextView
②在侧边栏页面中设置当前的菜单详情页(抽取方法)setCurrentDetailPager()
重点是拿到菜单详情页对象
先拿到MainActivity(mainUi),同拿到侧边栏同样,拿到主页
经过主页的mPagers集合,拿到新闻中心的对象
参考名getNewsCenterPager()
而后在NewsCenterPager类中建立方法setCurrentDetailPager(int position)索引传递
在侧边栏中,经过它的对象调用这个方法
11.,实现侧边栏详情页的切换
在NewsCenterPager建立的方法setCurrentDetailPager(int position)中,
从新给它所在的Fragment设置内容
建立一个集合保存下这四个菜单详情页pager.
在上面的方法里,拿到对应索引的pager对象,拿到布局
而后把view添加到帧布局中
添加的同时,也要初始化数据
额外1:添加以前要把帧布局中以前的View清理掉,removeAllViews();
额外2:新闻中心默认应该显示新闻菜单pager的内容
解析完数据,切换新闻详情页
额外3:更新标题,最简单方法,就是解析数据时候把网络数据的信息直接传进来
额外4:下方导航栏切换以后,再切换到新闻中心,侧边栏数据不变
须要在每次切换到新闻中心以后,会调用侧边栏设置数据的方法里,在这个方法里把侧边栏的索引归零(修改记录选中的变量便可)