【Android】异步加载布局探索

最近在做的项目页面复杂导致布局嵌套多层,而且又使用了百分比布局(可能主要是这个原因)导致页面加载的时候主线程会被阻塞,

那要想减少主线程阻塞,一来就是简化布局,减轻LayoutInflater的负担,二来就是异步加载布局。

项目当中用了rxjava,于是直接写个异步加载的工具类

public class InflaterUtil {

    public static void ansycInflate(final Context context, final int resource, @Nullable final ViewGroup root, final boolean attachToRoot, final AsyncInflate asyncInflate) {
        Observable
                .create(new ObservableOnSubscribe<View>() {
                    @Override
                    public void subscribe(ObservableEmitter<View> emitter) throws Exception {
                        View view = LayoutInflater.from(context).inflate(resource, root, attachToRoot);
                        emitter.onNext(view);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<View>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(View view) {
                        if (asyncInflate != null) asyncInflate.success(view);
                    }

                    @Override
                    public void onError(Throwable e) {
                        MLog.e(e.toString());
                    }

                    @Override
                    public void onComplete() {
                    }
                });
    }

}

在子线程加载布局为View对象,然后在主线程把view返回,来更新UI。

需要注意,在有些机型上,异步加载布局会在主线程的looper创建完成之前调用,所以依赖与handler和looper的view,

会出现异常,比如SurfaceView,TextClock等等。

对于这些view,可以这样处理,先使用ViewStub占位,等view异步加载完成后,再调用ViewStub的inflate方法来初始化。

布局文件占位

<ViewStub
                android:id="@+id/stub_slogan"
                android:layout="@layout/layout_slogan"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

 java代码动态初始化

InflaterUtil.ansycInflate(getContext(), R.layout.layout_top_left, leftContainer, true, new InflaterUtil.AsyncInflate() {
            @Override
            public void success(View view) {
                final ViewStub stub_slogan = view.findViewById(R.id.stub_slogan);
                stub_slogan.setOnInflateListener(new ViewStub.OnInflateListener() {
                @Override
                public void onInflate(ViewStub stub, View inflated) {
//                scrollTextView = view.findViewById(R.id.scrollText);
                sloganTextView = view.findViewById(R.id.tv_slogan);
            }
        });
      }
});        

这样就可以了

原文地址:https://www.cnblogs.com/liyilin-jack/p/10282385.html