【Android笔记】异步加载View,AsyncLayoutInflater原理

AsyncLayoutInflater是谷歌提供的异步加载UI工具,减少主线程消耗。本文介绍了其使用方法、初始化过程、加载原理,以及完整源码分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步加载View,AsyncLayoutInflater原理

AsyncLayoutInflater是谷歌提供的一个异步加载UI方案,其可以异步加载控件并回调给UI,以此减少主线程消耗。

使用

在应用的build.gradle中添加如下依赖

...
dependencies {
    ...
    implementation 'androidx.asynclayoutinflater:asynclayoutinflater:1.0.0'
}

依赖后,可以在任何能获取context的场景调用如下方法进行异步加载

    /* KOTLIN */

    /**
     * 示例方法
     *
     * @param ctx   上下文实例
     * @param layoutRes 目标布局文件id
     * @param parent    父布局
     */
    fun sample(ctx: Context, layoutRes: Int, parent: ViewGroup) {
   
        AsyncLayoutInflater(ctx).inflate(layoutRes, parent) {
    view, id, parentView ->
            Log.d("RESULT_INTRO", "view: 目标加载布局")
            Log.d("RESULT_INTRO", "id: 目标加载布局资源id")
            Log.d("RESULT_INTRO", "view: 父布局")
            
            // 该方法仅加载布局,父布局仅用来计算尺寸,不会将目标布局放入父布局
            parentView?.addView(view)
        }
    }
    /* JAVA */
    
    /**
     * 示例方法
     *
     * @param ctx   上下文实例
     * @param layoutRes 目标布局文件id
     * @param parent    父布局
     */
    void sample(Context ctx, int layoutRes, ViewGroup parent) {
   
        new AsyncLayoutInflater(ctx)
                .inflate(layoutRes, parent, (view, resid, parentView) -> {
   
                    Log.d("RESULT_INTRO", "view: 目标加载布局");
                    Log.d("RESULT_INTRO", "resid: 目标加载布局资源id");
                    Log.d("RESULT_INTRO", "view: 父布局");

                    // 该方法仅加载布局,父布局仅用来计算尺寸,不会将目标布局放入父布局
                    if (parentView != null) parentView.addView(view);
                });
    }

该异步加载仅相当于LayoutInflater#inflate(int, ViewGroup, boolean)方法中attachToRoot参数为false的结果。由于不知道异步加载结束后父布局会不会已被回收,所以加载结束后不会直接加入父布局,仅做尺寸计算

原理

打开AsyncLayoutInflater类,可以看到该类维护了一个LayoutInflater、一个用于将在加载完成后将事件回调给原线程(创建AsyncLayoutInflater的线程)的Handler,一个用来加载layout的线程。

初始化

    // AsyncLayoutInflater.java
    ...
       public AsyncLayoutInflater(@NonNull Context context) {
   
        mInflater = new BasicInflater(context);
        mHandler = new Handler(mHandlerCallback);
        mInflateThread = InflateThread.getInstance();
    }
    ...

在其构造函数中将前面提到的三个变量进行了初始化。可以看出其加载线程是一个静态内部类模式的单例。该线程维护了一个存放请求的队列,并在线程中死循环去从队列取加载请求并进行加载。

    // AsyncLayoutInflater.java
    // AsyncLayoutInflater.InflateThread.class
    
    ...
        @Override
        public void run() {
   
            while (true) {
   
                runInner();
            }
        }
        
        // Extracted to its own method to ensure locals have a constrained liveness
        // scope by the GC. This is needed to avoid keeping previous request references
        // alive for an indeterminate amount of time, see b/33158143 for details
        public void runInner() {
   
            InflateRequest request;
            try {
   
                request = mQueue.take();
            } catch (InterruptedException ex) {
   
                // Odd, just continue
                Log.w(TAG, ex);
                return
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值