android - 运行阻塞请求

标签 android firebase firebase-realtime-database

我读到 Firebase 在后台线程上运行其操作,并在 UI 线程上运行回调。

有没有办法运行阻塞的 Firebase 操作?

例如:

我知道 setValue() 不会返回 bool 值,我想问一下是否有类似的 API 可以执行类似以下代码的操作

// we are in a background thread

DatabaseReference ref = FirebaseDatabase.getInstance().getReference();

boolean success = ref.child("user").child("name").setValue("Arthur");

// code is blocked until operation completes

Log.d("MY_TAG", "successfull operation:" + success);

最佳答案

FirebaseDatabase API 不包含 setValue() 的阻塞形式.您可以使用返回的 Task在您自己的工作线程(非主)线程中添加阻塞:

    boolean success = false;
    DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
    Task task = ref.child("user").child("name").setValue("Arthur");

    try {
        Tasks.await(task);
        success = task.isSuccessful();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Log.d("MY_TAG", "successfull operation:" + success);

A Semaphore可用于阻塞读取。因为监听器回调在主线程上运行,所以这段代码只能在另一个线程上运行。如果在主线程上运行,它会死锁。

    final Semaphore sem = new Semaphore(0);

    DatabaseReference ref = FirebaseDatabase.getInstance().getReference();

    ref.child("user").child("name").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String name = dataSnapshot.getValue(String.class);
            Log.i("MY_TAG", "Name=" + name);
            sem.release();
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e("MY_TAG", "onCancelled: " + databaseError.getMessage());
            sem.release();
        }
    });

    try {
        sem.acquire();
    } catch (InterruptedException e) {
        Log.w("MY_TAG", "Interrupted");
    }

您还可以使用 Task 进行阻塞读取(在主线程之外):

    final TaskCompletionSource<DataSnapshot> taskSource = new TaskCompletionSource<>();
    final Task<DataSnapshot> task = taskSource.getTask();

    DatabaseReference ref = FirebaseDatabase.getInstance().getReference();

    ref.child("user").child("name").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            taskSource.setResult(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            taskSource.setException(databaseError.toException());
        }
    });

    try {
        Tasks.await(task);

        String name = task.getResult().getValue(String.class);
        Log.i("MY_TAG", "Name=" + name);
    } catch (ExecutionException e) {
        Log.e("MY_TAG", "Read failed: " + task.getException().getMessage());
    } catch (InterruptedException e) {
        Log.w("MY_TAG", "Read interrupted");
    }

关于android - 运行阻塞请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41990966/

相关文章:

Android:如何使用换行内容避免在圆形按钮的圆圈外按下?

android - Gradle离线同步问题

android - ContentProvider - 我需要 list 文件中的条目吗?

javascript - 根据用户锁定特定节点的读/写访问权限

javascript - Ionic 应用程序在初始化完成之前开始工作

firebase-realtime-database - 如何在 Flutter 的 FirebaseDatabase 插件中使用 ServerValue

firebase - 如果我不使用数据库,是否需要在firebase中更改安全规则?

Android 自定义对话框

ios - 如何在多个 View Controller 上使用数组?

javascript - 刷新后,angularjs firebase登录范围值不可用