【问题标题】:Send data to firestore inside a worker in Android将数据发送到 Android 工作人员内部的 Firestore
【发布时间】:2020-03-08 00:17:27
【问题描述】:

我正在尝试每 15 分钟将手机的位置信息发送到 Firestore。

我正在查看 Android 中的工作人员,但我读过的代码不起作用,因为它们是同步的,我正在调用异步方法来调用 firestore。

另外,我在worker中的比赛是MultiDexApplication类型,调用mFusedLocationClient.getLastLocation()时会抛出异常

这是我的工人的代码。

public class LocationWorker extends Worker {
    private final static String TAG = "LocationWorker";

    private FusedLocationProviderClient mFusedLocationClient;
    private Context mApplicationContext;
    private FirebaseFirestore mFireStoreRef;
    private String mCurrentUserID;

    public LocationWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
        mApplicationContext = getApplicationContext();
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mApplicationContext);
        mFireStoreRef = FirebaseFirestore.getInstance();
        mCurrentUserID = "Patrick";

    }

    @NonNull
    @Override
    public Result doWork() {
        mFusedLocationClient.getLastLocation()
                .addOnSuccessListener((Activity) mApplicationContext, new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(final Location location) {
                        // Got last known location. In some rare situations this can be null.
                        if (location != null) {

                            mFireStoreRef
                                    .collection("locations")
                                    .document(mCurrentUserID)
                                    .collection(DateFormat.getDateTimeInstance().format(new Date()))
                                    .add(location)
                                    .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                                        @Override
                                        public void onSuccess(DocumentReference documentReference) {
                                            Log.d(TAG, "Location added: " + location.toString());
                                        }
                                    });
                        }
                    }
                });
        return Result.success();
    }
}

我知道我无法在工作人员内部进行异步调用。但后来我想知道如何每 15 分钟将手机的位置信息发送到 Firestore?

【问题讨论】:

  • Firestore 的 API 是异步的这一事实并不妨碍您将它与 Jetpack Workmanager 一起使用。你有两个选择。 1)WorkManager 也提供异步 API(您返回一个 ListenableFuture,它会根据您的工作结果进行解析。2)使工作线程阻塞,直到调用完成,CountDownLatch 是一种常见的解决方案。选项 1 确实是正确的方法。
  • @DougStevenson 谢谢!顺便说一句,我会试试的。你知道关于在工作期间获取 AppContext 而不是在调用 getApplicationContext() 时获取 MultidexApplication 的任何事情吗?

标签: android firebase google-cloud-firestore androidx android-workmanager


【解决方案1】:

有一个上下文传递到 Worker 的构造函数中。如果您担心直接使用它,可以尝试将其存储在 WeakReference 中。

使用 ListenableWorker 时,线程由您决定。此示例运行为新线程创建的 Runnable 内的所有内容,但如果它更适合您,您可以选择不同的策略:

public class MyWorker extends ListenableWorker{

    private Context mContext;
    private FirebaseFirestore mDb;

    public MyWorker(Context context, WorkerParameters params){
        super(context, params);

        mContext = context; // Store the context passed into the worker
        mDb = FirebaseFirestore.getInstance();
    }

    @NonNull
    @Override
    public ListenableFuture<Result> startWork(){

        return CallbackToFutureAdapter.getFuture(new CallbackToFutureAdapter.Resolver<Result>() {
            @Nullable
            @Override
            public Object attachCompleter(@NonNull final CallbackToFutureAdapter.Completer<Result> completer)
                    throws Exception {

                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {

                        OnCompleteListener<DocumentReference> completeListener = new OnCompleteListener<DocumentReference>() {
                            @Override
                            public void onComplete(@NonNull Task<DocumentReference> task) {
                                if(task.isSuccessful()){
                                    // ...

                                    completer.set(Result.success());

                                }else{
                                    // Whether you return failure or retry here
                                    // depends on what makes the most sense for your situation
                                    completer.set(Result.failure());
                                }
                            }
                        };

                        Map<String, Object> data = new HashMap<>();
                        data.put("some_data", someData);

                        mDb.collection("myCollection")
                            .add(data)
                            .addOnCompleteListener(completeListener);
                    }
                };

                new Thread(runnable).start();

                return runnable;
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多