【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); } }); } });
这样就可以了