Realm和Retrofit,如何在UI线程外保存?

Realm and Retrofit, how to save outside the UI thread?

我正在使用 Retrofit to download a json of Clients, I then have to persist them with RealmClient 扩展 RealmObject)。问题是我有 15k Clients,所以保存需要几秒钟。如果我无法在线程之间传递 RealmObject,如何将我从 Retrofit 获得的客户端列表传递给 background thread

这是我现在拥有的代码,它会在我执行保存时阻止 UI 几秒钟

api.clients(token, date, new Callback<List<Client>>() {
            new Callback<LoginResponse>() {
    @Override
    public void success(List<Client> clients, Response response) {
        Logs.retrofit("Clients status: " + response.getStatus());
        if (response.getStatus() == 200) {
            //It's all good man!
            saveClients(clients);
            if (callbacks != null) callbacks.onClientListDownloadSuccessful();
        } else if (response.getStatus() == 401) {
            //Wrong token, refresh it and retry
            refreshLoginToken();
        } else {
            //Other error status
            if (callbacks != null)
                callbacks.onClientListDownloadError(response.getStatus());
        }
    }

    @Override
    public void failure(RetrofitError error) {
        Logs.retrofit("Client error: " + error.getMessage());
        if (error.getResponse() != null && error.getResponse()
                                                   .getStatus() == 401) {
            refreshLoginToken();
        } else if (callbacks != null) callbacks.onClientListDownloadError(0);
    }

private void saveClients(List<Client> clients) {
    Logs.realm("Saving clients to local db: " + clients.size());
    Realm realm = App.getCommercialiRealm(context);

    List<Long> ids = new ArrayList<>();
    realm.beginTransaction();
    for (Client client : clients) {
        if (client.isDeleted()) {
            //Delete client
            ids.add(client.getID());
        }
    }

    //Add or update clients
    realm.copyToRealmOrUpdate(clients);
    Logs.realm("Client in db " + realm.where(Client.class)
            .count());

    //Delete clients
    deleteClients(realm, ids);
    Logs.realm("Client in db after cleanup " + realm.where(Client.class)
            .count());

    realm.commitTransaction();
    PrefsUtils.saveLastSync(context, System.currentTimeMillis());
}

就我个人而言,我会尽量让我的服务层和持久层分离。解析对作为简单 POJO 实现的客户端 class 的网络响应,并仅在处理数据库时使用 RealmObjects(您需要在两个 'client' 实体之间使用某种映射实用程序)。

如果您真的想将 Retrofit 响应用作 RealmObjects,您可能需要在 API 界面中删除 'Callback' 格式并实施您自己的线程解决方案,以便 Retrofit 和领域操作在同一个线程中执行。

基本上,设置它以便您可以执行如下操作:

try {
    List<Client> clients = api.clients(token, date);
    saveClients(clients);
} catch(RetrofitError e){
    Response response = e.getResponse();
    if (response.getStatus() == 401) {
        // Wrong token, refresh it and retry
        refreshLoginToken();
    } else {
        // Propagate error on the UI thread or whatever :P
    }
}

在后台线程中。