使用methord返回值调用Firebase Firestore时无法在变量中获取数据

时间:2019-07-12 15:31:18

标签: android firebase google-cloud-firestore

当我从android中的Cloud Firestore获取数据时。它返回一个空变量。它应该返回标志值true或false。

public boolean checkIfUserAlreadyExists(final String email) {
        final boolean[] flag = {false};
        db.collection(context.getString(R.string.db_collection_users))
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : task.getResult()) {
                                if (document.getData().get(context.getString(R.string.db_field_email)).toString() != null && document.getData().get(context.getString(R.string.db_field_email)).toString().equals(email)) {
                                    Toast.makeText(context, "User Already exits", Toast.LENGTH_SHORT);
                                    Log.e(TAG, "User already exists" + document.getData().get("email").toString());
                                    flag[0] = true;
                                } else {
                                    Log.e(TAG, "User do not exists");
                                }
                            }
                        } else {
                            Log.e(TAG, "Error getting documents.", task.getException());
                        }
                    }
                });
        return flag[0];
    }

flag [0]应该返回true,但是在另一个活动中调用时它返回false。

1 个答案:

答案 0 :(得分:1)

addOnCompleteListener异步工作。

也就是说,您在设置flag[0]之后立即返回OnCompleteListener。到那时onComplete()不会被调用,因此flag[0]仍然具有初始值。该编译器预期会出现这种类型的错误,这就是为什么它警告您不能在回调方法内更改非最终变量的原因。但是您通过将其制成数组?

以一种奇怪的方式绕过了它

您可以通过多种方式解决此问题


解决方案1 ​​

代替返回值,而是从回调中访问值

illustration

public void checkIfUserAlreadyExists(final String email) {
    db.collection(context.getString(R.string.db_collection_users))
        .get()
        .addOnCompleteListener(new OnCompleteListener < QuerySnapshot > () {
            @Override
            public void onComplete(@NonNull Task < QuerySnapshot > task) {
                if (task.isSuccessful()) {


                    for (QueryDocumentSnapshot document: task.getResult()) {

                        if (document.getData().get(context.getString(R.string.db_field_email)).toString() != null && document.getData().get(context.getString(R.string.db_field_email)).toString().equals(email)) {
                            Toast.makeText(context, "User Already exits", Toast.LENGTH_SHORT);
                            Log.e(TAG, "User already exists" + document.getData().get("email").toString());

                            // User exists.
                            userTheResult(true);
                            return;

                        } else {
                            Log.e(TAG, "User do not exists");
                        }
                    }

                    // No user exists.
                    userTheResult(false);

                } else {
                    Log.e(TAG, "Error getting documents.", task.getException());
                }
            }
        });
}


解决方案2

您可以使用此类使线程等待直到获得结果。这样,您无需太多更改代码。您要做的就是简单地将类ThreadLockedTask<T>添加到您的项目中,并按照给出的示例使用它。

import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Ahamad Anees P.A
 * @version 1.0
 * @param <T> type
 */
public class ThreadLockedTask<T> {

    private AtomicReference<ResultWrapper<T>> mReference;

    public ThreadLockedTask() {
        mReference = new AtomicReference<>(new ResultWrapper<T>());
    }

    public T execute(Runnable runnable) {
        runnable.run();
        if (!mReference.get().mIsSet)
            lockUntilSet();
        return mReference.get().mResult;
    }

    private void lockUntilSet() {
        synchronized (this) {
            while (!mReference.get().isSet()) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public void setResult(T result) {
        synchronized (this) {
            ResultWrapper<T> wrapper = mReference.get();
            wrapper.setResult(result);
            wrapper.setIsSet(true);
            notify();
        }
    }

    public static class ResultWrapper<T> {
        private boolean mIsSet;
        private T mResult;

        public boolean isSet() {
            return mIsSet;
        }

        public T getResult() {
            return mResult;
        }

        void setIsSet(boolean isCompleted) {
            this.mIsSet = isCompleted;
        }

        void setResult(T result) {
            this.mResult = result;
        }
    }

}


用法

public boolean checkIfUserAlreadyExists(final String email) {
    ThreadLockedTask < Boolean > task = new ThreadLockedTask < > ();
    boolean flag = task.execute(new Runnable() {
        @Override
        public void run() {
            db.collection(context.getString(R.string.db_collection_users))
                .get()
                .addOnCompleteListener(new OnCompleteListener < QuerySnapshot > () {
                    @Override
                    public void onComplete(@NonNull Task < QuerySnapshot > task) {
                        if (task.isSuccessful()) {

                            for (QueryDocumentSnapshot document: task.getResult()) {

                                if (document.getData().get(context.getString(R.string.db_field_email)).toString() != null && document.getData().get(context.getString(R.string.db_field_email)).toString().equals(email)) {
                                    Toast.makeText(context, "User Already exits", Toast.LENGTH_SHORT);
                                    Log.e(TAG, "User already exists" + document.getData().get("email").toString());

                                    task.setResult(true);
                                    return;

                                } else {
                                    Log.e(TAG, "User do not exists");
                                }
                            }
                        } else {
                            Log.e(TAG, "Error getting documents.", task.getException());
                        }

                        task.setResult(false);
                    }
                });
        }
    });

    return flag;
}