美文网首页
怎么获取页面加载完成的最佳时机?

怎么获取页面加载完成的最佳时机?

作者: wan7451 | 来源:发表于2019-03-07 22:16 被阅读0次

    Android 开发页面的时候,一般的流程都是先加载页面,等页面加载完成后再执行其他后续操作。而获取页面加载完成的时机,有各种各样的方式。比如:

    1. 使用Handler延迟200毫秒加载
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        //加载数据
      }
    },200);
    
    1. 监听全局布局加载
    View root = findViewById(R.id.container);
    root.getViewTreeObserver()
        .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
            //加载数据
            root.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });
    
    1. view的Post方法
    view.post(new Runnable() {
      @Override
      public void run() {
                    
      }
    });
    

    今天无意中发现一个骚操作,使用 IdleHandler 获取页面加载完成的时机,代码很简单

    @Override
    protected void onResume() {
        super.onResume();
        getMainLooper().myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                //加载完成
                //false 执行一次,true 执行多次
                return false;
            }
        });
    }
    

    IdleHandler 即是懒惰的Handler。IdleHandler的方法执行时机是在MessageQueue中没有Message时执行,也就是主线程空闲的时候执行。熟悉Handler、Looper的同学一看源码就清楚了。

    public static void loop() {
        //....
        for (;;) {
            //....
            Message msg = queue.next(); // might block
            //....
        }
    }
    

    在Looper的loop()方法中,会从消息队列中取出msg,然后再执行 msg.target.dispatchMessage(msg)。接下来重点看下MessageQueue.next()方法。

    Message next() {
      //...
      // If first time idle, then get the number of idlers to run.
      // Idle handles only run if the queue is empty or if the first message
      // in the queue (possibly a barrier) is due to be handled in the future.
      if (pendingIdleHandlerCount < 0
        && (mMessages == null || now < mMessages.when)) {
        pendingIdleHandlerCount = mIdleHandlers.size();
      }
      if (pendingIdleHandlerCount <= 0) {
        // No idle handlers to run.  Loop and wait some more.
        mBlocked = true;
        continue;
      }
    
      if (mPendingIdleHandlers == null) {
        mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
      }
        mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
      }
    
      // Run the idle handlers.
      // We only ever reach this code block during the first iteration.
      for (int i = 0; i < pendingIdleHandlerCount; i++) {
        final IdleHandler idler = mPendingIdleHandlers[i];
        mPendingIdleHandlers[i] = null; // release the reference to the handler
    
        boolean keep = false;
        try {
          keep = idler.queueIdle();
        } catch (Throwable t) {
            Log.wtf(TAG, "IdleHandler threw exception", t);
        }
    
        if (!keep) {
        synchronized (this) {
        mIdleHandlers.remove(idler);
        }
      }
    }
    

    从上面的代码以及注释中就能看出,当Message为空的时候,系统就会执行IdleHandler 数组中的queueIdle()方法。所以说IdleHandler是在空闲的时候执行逻辑的。

    那么在为什么说onResume()方法中 queueIdle() 是在布局加载完成调用的,请参考这个文章。
    https://mp.weixin.qq.com/s/KpeBqIEYeOzt_frANoGuSg

    相关文章

      网友评论

          本文标题:怎么获取页面加载完成的最佳时机?

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