Android: 重写 Loader,解决 registerListener 已注册问题

个人博客地址: 斯科特安的时间

使用 LoaderManager 管理 Loader,会默认注册一个 OnLoadCompleteListener , 而这个 Listener 只能注册一个。重复注册会报这个错误:

Caused by: java.lang.IllegalStateException:

There is already a listener registered

at android.support.v4.content.Loader.registerListener(Loader.java:130)

源码是这样:

public void registerListener(int id, OnLoadCompleteListener listener) {
    if (mListener != null) {
        throw new IllegalStateException("There is already a listener registered");
    }
    mListener = listener;
    mId = id;
}

我们看到方法名叫 register... 自然想到可以使用 unregister... 方法。
然而由于这个 listener 是 LoaderManager 帮助注册的,除非使用一些非常规方法 (比如反射),我们不能也不合适去手动 unregister。

别人的解决方案

网络很多人认为这是 android 的 bug,可以通过每次重新新建 Loader 解决:

Override  
public YourLoader onCreateLoader(int arg0, Bundle bundle) {
    return new YourLoader(getContext()...);  
}  

然而这个方法并不是特别优雅

一个比较优雅的解决方案是 extends Loader, 重写一套回调方法。

查看源码我们看看原来怎么回调的:

public void deliverResult(D data) {
    if (mListener != null) {
        mListener.onLoadComplete(this, data);
    }
}
public void deliverCancellation() {
    if (mOnLoadCanceledListener != null) {
        mOnLoadCanceledListener.onLoadCanceled(this);
    }
}

那我们只需要重写这两个方法就可以了,新的 ObservableLoader 如下:

public abstract class ObservableLoader extends AsyncTaskLoader {
    public ObservableLoader(Context context) {
        super(context);
    }

    @Override
    public void deliverResult(D data) {
        super.deliverResult(data);
        notifyLoadCompleted(this, data);
    }

    @Override
    public void deliverCancellation() {
        super.deliverCancellation();
        notifyLoadCancelled(this);
    }

    public interface LoaderObserver {
        void onLoadCompleted(Loader loader, D data);
        void onLoadCancelled(Loader loader);
    }

    private List> mObservers = new ArrayList<>();

    public void addObserver(@NonNull LoaderObserver observer) {
        if (!mObservers.contains(observer)) {
            mObservers.add(observer);g
        }
    }

    public void removeObserver(@NonNull LoaderObserver observer) {
        if (mObservers.contains(observer)) {
            mObservers.remove(observer);
        }
    }

    public void notifyLoadCompleted(Loader loader, D data) {
        for (LoaderObserver observer : mObservers) {
            observer.onLoadCompleted(loader, data);
        }
    }

    public void notifyLoadCancelled(Loader loader) {
        for (LoaderObserver observer : mObservers) {
            observer.onLoadCancelled(loader);
        }
    }
}

你可能感兴趣的:(Android: 重写 Loader,解决 registerListener 已注册问题)