Google 在 Android 上驱动器 API 的并发问题

Concurrency Issues with Google Drive API on Android

我在将 Google 驱动器 API 集成到我的 Android 应用程序时遇到了一些问题。基本上,我正在尝试创建一个文件夹来存储我的错误日志。问题是偶尔,线程会 运行,并且在需要创建文件时文件夹不会创建,因此应用程序崩溃。我正在思考如何避免这种情况,目前尝试了几种方法,包括在文件夹回调中进行文件夹分配,但都无济于事。有时我很幸运(不幸的是,尤其是在调试时)并且文件保存正常,但我显然需要解决并发问题。如果上下文需要更多代码,请告诉我。

protected void onPause() {
    // TODO Find the right place for this
    if (!mDriveLogList.isEmpty()) {
        // Perform I/O off the UI thread.
        // TODO Fix to use RxJava
        new Thread() {
            @Override
            public void run() {
                Timber.i("Starting File Creation");
                // write content to DriveContents
                if (mDriveContents == null) {
                    Timber.e("Drive Contents Were Null");

                } else {
                    OutputStream outputStream = mDriveContents.getOutputStream();
                    Writer writer = new OutputStreamWriter(outputStream);
                    //TODO Clean/Refactor
                    try {
                        writer.write("Status Log For: " + DateHelper.getDate() + "\n");
                        for (String logEntry : mDriveLogList) {
                            writer.write(logEntry + "\n");
                        }
                        writer.close();
                    } catch (IOException e) {
                        Timber.e(e, "Error During Drive Contents Callback");
                    }

                    MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                            .setTitle(SURVEIL_DROID + " " + DateHelper.getDate())
                            .setMimeType("text/plain")
                            .setStarred(true).build();

                    MetadataChangeSet folderSet = new MetadataChangeSet.Builder()
                            .setTitle("SurveilCustomFolder")
                            .build();

                    Drive.DriveApi.getRootFolder(mGoogleApiClient)
                            .createFolder(mGoogleApiClient, folderSet)
                            .setResultCallback(folderCallback);

                        mDriveFolder = mFolderId.asDriveFolder();

                        mDriveFolder.createFile(mGoogleApiClient, changeSet, mDriveContents)
                                .setResultCallback(fileCallback);

                    mDriveLogList.clear();
                }
            }
        }.start();

您可以使用倒计时闩锁(参见 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)来帮助同步。像

protected void onPause() {
    // TODO Find the right place for this
    if (!mDriveLogList.isEmpty()) {

        // Perform I/O off the UI thread.
        // TODO Fix to use RxJava
        new Thread() {
            @Override
            public void run() {
                final protected CountDownLatch connectionLatch = new CountDownLatch(1);
                protected boolean folderCreated = false;                
                Timber.i("Starting File Creation");
                // write content to DriveContents
                if (mDriveContents == null) {
                    Timber.e("Drive Contents Were Null");

                } else {
                    OutputStream outputStream = mDriveContents.getOutputStream();
                    Writer writer = new OutputStreamWriter(outputStream);
                    //TODO Clean/Refactor
                    try {
                        writer.write("Status Log For: " + DateHelper.getDate() + "\n");
                        for (String logEntry : mDriveLogList) {
                            writer.write(logEntry + "\n");
                        }
                        writer.close();
                    } catch (IOException e) {
                        Timber.e(e, "Error During Drive Contents Callback");
                    }

                    MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                            .setTitle(SURVEIL_DROID + " " + DateHelper.getDate())
                            .setMimeType("text/plain")
                            .setStarred(true).build();

                    MetadataChangeSet folderSet = new MetadataChangeSet.Builder()
                            .setTitle("SurveilCustomFolder")
                            .build();

                    Drive.DriveApi.getRootFolder(mGoogleApiClient)
                            .createFolder(mGoogleApiClient, folderSet)
                            .setResultCallback(new
                                ResultCallback<DriveFolderResult>() {
                                    @Override
                                    public void onResult(DriveFolderResult result) {
                                       folderCreated = result.getStatus().isSuccess();
                                       connectionLatch.countDown(); // Release latch                                  
                                    }
                                });
                    try {
                        connectionLatch.await() ;
                    } catch (InterruptedException e) {              
                        e.printStackTrace();
                        return;
                    }
                    if (folderCreated) {
                        mDriveFolder = mFolderId.asDriveFolder();
                        mDriveFolder.createFile(mGoogleApiClient, changeSet, mDriveContents)
                                    .setResultCallback(fileCallback);                        
                        mDriveLogList.clear();
                    }
                }
            }
        }.start();  
    }
}

应该可以。

createFolder() returns 一个 PendingResult,您可以使用 PendingResult 的 await() 方法之一来阻塞,直到创建文件夹。看这里:(https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html#await())