美文网首页
【Android面试题】高级UI面试题——View绘制流程与自定

【Android面试题】高级UI面试题——View绘制流程与自定

作者: 小城哇哇 | 来源:发表于2023-08-24 17:29 被阅读0次

View绘制流程与自定义View注意点

详细讲解

本问题的系统回答大家可以移步到高级UI课程里面,这个问题是一个综合问题,设计自定义View的各方面

这道题想考察什么?

是否了解View绘制流程与自定义View注意点与实际场景使用,是否熟悉View绘制流程与自定义View注意事项

考察的知识点

View绘制流程与自定义View注意事项的概念在实际项目中使用

考生应该如何回答

这个问题先需要回答View的绘制流程,然后再回到自定义View的注意点。

9.2.1. View的绘制流程

这个问题的回答请看7-1题,View的绘制原理。

9.2.2. 自定义View注意点?

1) View需要实现四个构造函数

自定义View中构造函数有四种

    //  主要是在java代码中new一个View时所调用,没有任何参数,一个空的View对象
    public ChildrenView(Context context) {
        super(context);
    }
    
    // 在布局文件中使用该自定义view的时候会调用到,一般会调用到该方法
    public ChildrenView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    
    //如果你不需要View随着主题变化而变化,则上面两个构造函数就可以了
    //下面两个是与主题相关的构造函数
   public ChildrenView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ChildrenView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

四个参数解释:

context:上下文

AttributeSet attrs:在xml中定义的参数内容

int defStyleAttr:主题中优先级最高的属性

int defStyleRes: 优先级次之的内置于View的style(这里就是自定义View设置样式的地方),只有当defStyleAttr为0或者当前Theme中没有给defStyleAttr属性赋值时才起作用.

在android中的属性可以在多个地方进行赋值,涉及到的优先级排序为:在布局xml中直接定义 > 在布局xml中通过style定义 > 自定义View所在的Activity的Theme中指定style引用 > 构造函数中defStyleRes指定的默认值

2)自定义View的种类各不相同,须要根据实际须要选择一种简单低成本的方式来实现,尽可能的减少UI的层级,view的种类如下,开发中需要尽可能的选择适合自己的。
  • 继承View重写onDraw方法

主要用于实现不规则的效果,也就是说这种效果不适宜采用布局的组合方式来实现。也就是需要使用canvas,Paint,运用算法去“绘制”了。采用这种方式须要本身支持wrap_content,padding也须要本身处理canvas。

  • 继承ViewGroup派生特殊的Layout

主要用于实现自定义的布局,看起来很像几种View组合在一块儿的时候,可使用这种方式。这种方式须要合适地处理ViewGroup的测量和布局,尤其在测量的时候需要注意padding 和margin,比如:自定义一个自动换行的LinerLayout等。

  • 继承特定的View,好比TextView

这种方法主要是用于扩展某种已有的View,增长一些特定的功能。这种方法比较简单,也不须要本身支持wrap_content和padding。这种效果就相当于我们使用imageView来实现一个圆形的imageView。

  • 继承特定的ViewGroup,好比LinearLayout

这种方式也比较常见,也就是基于原来已经存在的layout,在其上去添加新的功能。和上面的第2种方法比较相似,第2种方法更佳接近View的底层。

3)View需要支持padding

直接继承View的控件需要在onDraw方法中处理padding,否则用户设置padding属性就不会起作用。直接继承ViewGroup的控件需要在onMeasure和onLayout中考虑padding和子元素的margin对其造成的影响,不然将导致padding和子元素的margin失效。

4)尽量不要在view中使用handler

如果在view中需要使用handler来处理异步信息,这个时候尽量使用view中的post方法,因为view中给用户提供了post方法,这个方法的处理逻辑是:将Runable 的action 保存到一个队列,在viewRootImpl里面执行度量后再添加进Handler的MessageQueue中,这样就保障了action里面执行的内存是在完成度量 后的结果,避免了使用延迟消息带来的困扰具体的代码如下:

public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
        
    ...
        
    public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
    
        // Postpone the runnable until we know on which thread it needs to run.
        // Assume that the runnable will be successfully placed after attach.
        getRunQueue().post(action);
        return true;
    }

    public boolean postDelayed(Runnable action, long delayMillis) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.postDelayed(action, delayMillis);
        }
    
        // Postpone the runnable until we know on which thread it needs to run.
        // Assume that the runnable will be successfully placed after attach.
        getRunQueue().postDelayed(action, delayMillis);
        return true;
    } 
    
    ...
}

5)在自定义view的onMeasure,onDraw,onLayout方法中尽量少使用局部变量

由于onMeaaure &onDraw&onLayout这3个函数都可能存在频繁调用的可能,尤其在动画里面,onDraw是非常频繁的调度的,在这些频繁被调用的函数里面,开发过程中一定要尽量避免创建局部对象,尤其是比较占用内存的像bitmap等的局部对象,这很容易产生内存抖动,而内存抖动容易带来手机app的卡顿,具体的细节大家可以去享学课堂查找对应的课程进行学习。

最后

有需要以上面试题的朋友可以关注一下哇哇,以上都可以分享!!!

相关文章

网友评论

      本文标题:【Android面试题】高级UI面试题——View绘制流程与自定

      本文链接:https://www.haomeiwen.com/subject/jhxvmdtx.html