首页 > 解决方案 > 在 Realm 中实现回调并将其设置在 Presenter MVP 中以进行异步工作

问题描述

在第一个问题中,我的方式是加载异步数据,当我完成演示者的 1 个方法时,我调用了第二个方法,但此时我的数据仍在加载。好吧,在那之后我解决了这个问题,我需要为领域方法设置一些回调以确保我的数据已加载,下载后我需要从数据库中获取它并反映在视图中。但是我的实现接口有一些问题。做这个的最好方式是什么?我将尝试编写以下代码:

在我的演讲者中:

getViewState().showListProgress();
    repository.loadDataFromNetworkToDB();

    List<Anime> animeList = repository.loadDataFromDbToPresenter();
    if (animeList.size() == 0) {
        System.out.println("you are loosing!S");
        Throwable error = new Throwable();
        onLoadingFailed(error);
    } else {
        onLoadingFinish();
        onLoadingSuccess(animeList);
    }

我将数据保存到领域的基本功能:

public void saveToDatabase(final OnTransactionCallback onTransactionCall) {
    try {

        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                for (Anime a : animeList) {
                    Anime anime = new Anime();
                    anime.setFromEntity(a);
                    System.out.println("title: " + anime.getTitle() + " saveToDb: ");
                    realm.copyToRealmOrUpdate(anime);
                }
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                if (onTransactionCall != null) {
                    onTransactionCall.onRealmSuccess();
                }
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                if (onTransactionCall != null) {
                    onTransactionCall.onRealmError();
                }
            }
        });
    } finally {
        if (realm != null) {
            realm.close();
        }
    }
}

public interface OnTransactionCallback {
    boolean onRealmSuccess();

    boolean onRealmError();
}

之后,我从网络下载数据并在模型中使用了两个函数:

public void loadDataFromNetworkToDB() {
    Realm realm = Realm.getDefaultInstance();

    ghibliService.getAnimeList()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(list -> {
                AnimeDbHelper dbHelper = new AnimeDbHelper(realm, list);
                dbHelper.saveToDatabase(this);
            });
}

@Override
public List<Anime> loadDataFromDbToPresenter() {
    List<Anime> animeList = new ArrayList<>();
    Realm realm = Realm.getDefaultInstance();
    try {
        final RealmResults<Anime> animeResults = realm.where(Anime.class).findAll();
        for (int i = 0; i < animeResults.size(); i++) {
            animeList.add(animeResults.get(i).toEntity());
        }
    } finally {
        if (realm != null) {
            realm.close();
        }
    }
    return animeList;

}

@Override
public boolean onRealmSuccess() {
    System.out.println("Success");
    return true;
}

@Override
public boolean onRealmError() {
    System.out.println("Error");
    return false;
}

标签: androidrealmandroid-mvp

解决方案


好的,下面的这段代码解决了我的问题,但是在我获得更新的列表对象后,我捕获了这样的异常:

I/art: Background sticky concurrent mark sweep GC freed 5614(449KB) AllocSpace objects, 18(288KB) LOS objects, 33% free, 1691KB/2MB, paused 5.354ms total 10.731ms
I/art: Background sticky concurrent mark sweep GC freed 7039(557KB) AllocSpace objects, 22(352KB) LOS objects, 39% free, 1561KB/2MB, paused 10.554ms total 15.931ms 

显然,presenter 应该有自己的生命周期,并且在某个地方我们需要删除 liveData。在我的模型中:

public RealmLiveData<Anime> findAnimes() {
    Realm realm = Realm.getDefaultInstance();
    RealmLiveData<Anime> realmLiveData;
    try {
        realmLiveData = new RealmLiveData<>(realm.where(Anime.class).findAllAsync());
    } finally {
        if (realm != null) {
            realm.close();
        }
    }
    return realmLiveData;
}

在我的演讲者中:

@Override
public void loadData() {
    view.onDataStarted();

    repository.getAnimeFromNetwork();

    liveData = repository.findAnimes();

    liveData.observeForever(new Observer<RealmResults<Anime>>() {
        @Override
        public void onChanged(@Nullable RealmResults<Anime> animes) {
            if (animes != null) {
                if (animes.size() == 0) {
                    //nothing
                    System.out.println("Result realmResult: " + animes.size());
                } else {
                    view.onDataCompleted();
                    System.out.println("My result before Background sticky concurrent mark sweep GC: " + animes.size());
                    List<Anime> animeList = new ArrayList<>();
                    animeList.addAll(animes);
                    view.showData(animeList);
                    //Trying to stop liveData - helplessness
                    liveData.removeObserver(this::onChanged);
                }
            } else {
                System.out.println("null" + animes);
            }
        }
    });

RealmLive 数据:

public class RealmLiveData<T extends RealmModel> extends LiveData<RealmResults<T>> {
private RealmResults<T> results;
private final RealmChangeListener<RealmResults<T>> listener =
        new RealmChangeListener<RealmResults<T>>() {
            @Override
            public void onChange(RealmResults<T> results) {
                setValue(results);
            }
        };
public RealmLiveData(RealmResults<T> realmResults) {
    results = realmResults;
}
@Override
protected void onActive() {
    results.addChangeListener(listener);
}
@Override
protected void onInactive() {
    results.removeChangeListener(listener);
}

推荐阅读