Android基础之View

2018-11-21  本文已影响0人  KD小帅

1.fragment

在fragment中为什么有时getActivity()会为null?Fragment试图为什么有的时候会重叠,怎么产生的,又如何解决?

答:如果app长时间在后台运行,再次进入app的时候可能会出现crash,而且fragment会有重叠现象。如果系统内存不足、切换横竖屏、app长时间在后台运行,Activity都可能会被系统回收然后重建,但Fragment并不会随着Activity的回收而被回收,创建的所有Fragment会被保存到Bundle里面,从而导致Fragment丢失对应的Activity。

出现上面这种情况时,app发生的变化如下:

1、在前面提到的几种情况下系统回收了MyActivity

2、通过onSaveInstanceState保存MyFragment的状态

3、用户再次点击进入app

4、由于MyActivity被回收,系统会重启MyActivity,根据之前保存的MyFragment的状态恢复fragment

5、MyActivity的代码逻辑中,会再次创建新的MyFragment

6、页面出现混乱,覆盖了两层的fragment。假如恢复的MyFragment使用到了getActivity()方法,会报空指针异常

对于上面的问题,可以考虑下面这两种解决办法:

1、不保存fragment的状态:在MyActivity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState);注释掉,让其不再保存Fragment的状态,达到fragment随MyActivity一起销毁的目的。

2、重建时清除已经保存的fragment的状态:在恢复Fragment之前把Bundle里面的fragment状态数据给清除。方法如下:

        if(savedInstanceState!= null)

        {

            String FRAGMENTS_TAG =  "android:support:fragments";

            savedInstanceState.remove(FRAGMENTS_TAG);

        }

Fragment的replace和add的区别

答:Fragment的容器一个FrameLayout,add 的时候是把所有的Fragment一层一层的叠加到了 FrameLayout 上了,而 replace 的话首先将该容器中的其他Fragment去除掉,然后将当前Fragment添加到容器中。

一个Fragment 容器中只能添加一个 Fragment 种类,如果多次添加则会报异常,导致程序终止,而replace则无所谓,随便切换。

因为通过add 的方法添加的Fragment,每个Fragment 只能添加一次,因此如果要想达到切换效果,需要通过Fragment的的hide和show方法结合者使用。将要显示的show出来,将其他hide起来。这个过程Fragment的生命周期没有变化。

通 过 replace 切 换 Fragment , 每 次 都 会 执 行 上 一 个 Fragment 的onDestroyView,新Fragment的onCreateView、onStart、onResume方法。

基于以上不同的特点我们在使用的使用一定要结合着生命周期操作我们的视图和数据。

getFragmentManager,getSupportFragmentManager ,getChildFragmentManager三者之间的区别 

答:getFragmentManager()所得到的是所在fragment 的父容器的管理器,

getChildFragmentManager()所得到的是在fragment  里面子容器的管理器。

getSupportFragmentManager()主要用于支持 3.0以下android系统版本,3.0以上可以直接调用getFragmentManager() ,因为fragment是3.0以后才出现的组件,为了这之前的系统版本也能使用fragment,借助V4包里面的getSupportFragmentManager()方法来间接获取FragmentManager()对象,3.0版本之后,有了Fragment的api,就可以直接使用getFragmentManager()这个方法来获取对象。

2.自定义View

requestLayout、invalidate与postInvalidate作用与区别

答:requestLayout : 当当前布局的宽高发生改变的时候, 此时需要重新调用父view的onMeaure和onLayout, 来给子view重新排版布局

invalidate : 让页面刷新, 重新调用onDraw方法,

postInvalidate : 在子线程来让页面来进行刷新的方法

onlayout,onDraw,DrawChild区别与联系

答:onLayout():View需要给自己设置大小和位置了或者ViewGroup需要给子View和ViewGroup自身时调用。

onDraw()方法,View的绘制流程一共包括三步:①测量measure;②布局layout;③绘制draw;onDraw()方法就是在第三布绘制时发生,开发者已经测量好View的大小,设置好View的布局,剩下最后一步就是,具体画出这个布局。画的方法就是onDraw(),每个View都需要利用这个方法画出自己,ViewGroup除非设置了背景,否则不用调用该方法。

drawChild()去重新回调每个子视图的draw()方法


3.View工作流程

什么是MeasureSpec,主要作用是什么?

答:MeasureSpec是View的一个静态内部类,它通过将SpecMode和SpecSize打包成一个int值来避免过多的对象内存分配,并提供了打包和解包方法MeasureSpec提供了三个方法

1)makeMeasureSpec(int size,int mode):size参数由程序员自己设定,mode必须是specMode的三个值中的一个

2)getMode(int measureSpec):见名知意,方法返回specMode的三个值中的一个,注意方法参数measureSpec,这个参数的值是怎么得来的呢?正是由makeMeasureSpec方法计算出来的

3)getSize(int measureSpec):获取View的大小,方法参数的值同样是由makeMeasureSpec计算的出来的。

MeasureSpec代表一个32位int值,高2位代表SpecMode,低30位代表SpecSize,SpecMode是指测量模式,而SpecSize是指在某种测量模式下的规格大小。

SpecMode有三类,每一类都表示特殊的含义,如下所示:

* UNSPECIFIED

父容器不对View有任何限制,要多大给多大,这种情况一般用于系统内部,表示一种测量状态

* EXACTLY

父容器已经检测出View所需要的精确大小,这个时候View的最终大小就是SpecSize所指定的值。它对应于LayoutParams中的match_parent和具体的数值这两种模式。

* AT_MOST

父容器指定了一个可用大小即SpecSize,View的大小不能大于这个值,具体是什么要看不同View的具体实现。它对应于LayoutParams中的wrap_content。

普通View的MeasureSpec 的创建规则

getWidth()方法和getMeasureWidth()区别呢?

答:getwidth():viewGroup的遍历每个子view,子view的layout()方法测量的结果。测量方式:getwidth=子布局右侧-子布局左侧;

getMeasuredWidth():viewGroup的遍历每个子view,子view的最近一次调用measure()方法测量后得到的,就是View的宽度。

上一篇下一篇

猜你喜欢

热点阅读