Android多线程,访问Room和http请求

时间:2018-06-13 14:32:59

标签: android multithreading thread-safety retrofit android-room

在我的应用程序中,我有一个不断涌入的数据和一个在X时间过后触发的调度程序,比方说20秒。触发时,会运行一个函数,将当前批量数据发送到API,如果网络连接可用,或将其保存在应用程序的Room数据库中。

所以我的问题出现在以下情况中。假设我有应用程序打开收集数据1小时但没有互联网连接。应用程序应该将所有这180个20秒的捆绑包保存在数据库中,这样做没有问题,每次调度程序触发时都会保存每个捆绑包。

现在说我决定打开我的WiFi并重新建立连接。这意味着从现在开始,所有20秒的捆绑包都应该上传到服务器,并且已经存储在数据库中的所有捆绑包都应排队等候发送到服务器。

以下代码块包含调度程序每20秒调用一次的函数。如果没有互联网,则toCache标志为真,并且应该在房间中保存数据。

ExecutorService exec = Executors.newSingleThreadExecutor();
    exec.execute(() -> {
        fromDb = (ArrayList<DataModel>) dataDB.userDAO().getData();
        if (fromDb.size() != 0)
            hasCachedData = true;

        if (toCache) {
            dataDB.userDAO().insertData(new DataModel(req));

        } else {
            synchronized (this) {
                if (hasCachedData) {
                    //Begin uploading data from the database

                    hasCachedData = false;
                    ArrayList<Observable<?>> requests = new ArrayList<>();
                    for (DataModel d : fromDb) {
                        requests.add(api.sendDeviceDataObs(new DataRequestModel(d)).onErrorReturn(throwable -> null));
                    }

                    Observable.zip(
                            requests,
                            objects -> {
                                // Objects[] is an array of combined results of completed requests
                                // do something with those results and emit new event
                                for (int i = 0; i < objects.length; i++) {
                                    if ((objects[i]) != null) {
                                        toRemove.add(fromDb.get(i));
                                    }
                                }
                                return new Object();
                            })
                            // After all requests had been performed the next observer will receive the Object, returned from Function
                            .subscribe(
                                    // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
                                    o -> {
                                        dataDB.userDAO().deleteData(toRemove.toArray(new DataModel[toRemove.size()]));
                                        fromDb.removeAll(toRemove);
                                        toRemove.clear();
                                        if (fromDb.size() != 0) {
                                            hasCachedData = true;
                                        }
                                        Log.d("lol", o.toString());
                                        //Do something on successful completion of all requests
                                    }, e -> {
                                        toRemove.clear();
                                        hasCachedData = true;
                                        Log.d("error", e.toString());
                                    }
                            );
                }
            }


            // Send current data to server with Retrofit
            api.sendDeviceData(req).enqueue(new Callback<ResponseBody>() { ... }

我面临的问题是我得到重复的数据。我相信,当重新建立连接后会发出很多请求,并且当下一个20秒触发器触发时,会发生从数据库中检索和上传数据的代码再次运行。

这有更好的实施吗?我错过了什么吗?另外,Observables.zip()有效,但我无法检查每个响应是否为200OK,这不是错误处理的理想选择。

提前致谢。

0 个答案:

没有答案