美文网首页
2. Android基础

2. Android基础

作者: 努力生活的西鱼 | 来源:发表于2019-10-15 19:06 被阅读0次
一. 为什么在子线程创建Handler会抛异常?如何正确使用

Handler的工作是依赖于Looper的,而Looper消息队列又是属于某一个线程ThreadLocal是线程内部的数据存储类,通过它可以在指定线程中存储数据,其他线程则无法获取到),其他线程不能访问。因此Handler就是间接跟线程是绑定在一起了。因此要使用Handler必须要保证Handler所创建的线程中有Looper对象并且启动循环。因为子线程中默认是没有Looper的,所以会报错。

正确的使用方法是:
public class WorkThread extends Thread {

    private Handler mHandler;

    public Handler getmHandler() {
        return mHandler;
    }

    public void quit() {
        mHandler.getLooper().quit();
    }

    @Override
    public void run() {
        super.run();
        // 创建该线程对应的Looper
        // 内部实现:
        // 1. new Looper();
        // 2. 将1步中的Looper放到ThreadLocal中,ThreadLocal是保存数据的,主要应用场景是: 线程间数据互不影响的情况
        // 3. 在1步中的Looper的构造函数中new MessageQueue();
        // 其实就是创建了该线程对应的Looper,Looper里创建MessageQueue来实现消息机制
        Looper.prepare(); // 初始化当前线程的Looper
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d("WorkThread", (Looper.getMainLooper() == Looper.myLooper()) + "," + msg.what);
            }
        };
        // 开启消息的死循环处理,即dispatchMessage
        Looper.loop();
        // 注意这3个的顺序不能颠倒
        Log.d("WorkThread", "end");
    }
}
二. 谈谈Android的事件分发机制

事件的传递流程:
Activity(PhoneWindow) -> DecorView -> ViewGroup -> View。事件分发过程中三个重要的方法: dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent();事件传递规则一般一次点击会有一系列的MotionEvent、可以简单分为:down -> move -> ... -> move -> up,当一次event分发到ViewGroup时,ViewGroup收到事件后调用dispatchTouchEvent,在dispatchTouchEvent中先检查是否要拦截,若拦截则ViewGroup处理事件,否则交给有处理能力的子容器处理。

三. 自定义控件优化方案
  1. 为了加速你的view,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。
  1. 你还需要尽可能的减少onDraw被调用的次数,大多数时候导致onDraw都是因为调用了invalidate(),因此请尽量减少调用invalidate()的次数。如果可能的话,尽量调用含有4个参数的invalidate()方法而不是没有参数的invalidate()。没有参数的invalidate()会强制重新绘制整个view。
  1. 另外一个非常耗时的操作是请求layout。任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级,来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View的层级是扁平化的,这样对提高效率很有帮助。如果你有一个复杂的UI,你应该考虑写一个自定义的ViewGroup来执行它的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。这个PieChart例子展示了如何继承ViewGroup作为自定义view的一部分。PieChart有子view,但是它从来不测量它们。而是根据它自身的layout法则,直接设置它们的大小。

相关文章

网友评论

      本文标题:2. Android基础

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