检索firebase.Timestamp.toDate时发生Firestore NullPointerException(FieldValue.serverTimestamp更新缓慢更新)

时间:2018-09-06 02:53:11

标签: java android firebase google-cloud-firestore

调用batch.commitdocRef.update(其中一部分调用FieldValue.serverTimeStamp以更新提交时间)后,我调用finish();返回上一个加载了recycleView更新的文档列表。

我收到此错误:

  

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'java.util.Date com.google.firebase.Timestamp.toDate()'

我怀疑FieldValue.servertimeStamp需要花费更多的时间进行计算,并且应用程序崩溃。但是,recyclerView从中提取日期时间的同一字段已经具有旧值。

我不确定为什么不检索旧值,而是崩溃为null。

问题1)在计算新的日期时间之前,FieldValue.servertimeStamp是否使该字段为空?

我的猜测是,此特定呼叫正在等待Firebase服务器的答复,因此花费更多时间,但其他呼叫首先在设备上本地完成,然后再在云中进行更新。感谢您的一些见识。

同时,作为一种解决此异步错误的解决方法,我在等待onCompleteSuccess响应时使用了Thread.sleep线程循环:

FirestoreFieldUpdated = false;
Thread myThread = new Thread(
     new Runnable() {
          @Override
          public void run() {
              try {
                     while (!FirestoreFieldUpdated) { //db.updateFields will change FirestorefieldUpdated to true uponSuccess
                           Thread.sleep(1000);
                     }
                  } catch (InterruptedException e) {
                        e.printStackTrace();
                  } finally {
                       finish();
                  }
          }
     }
);
myThread.start();

Q2)是否有更优雅的方法或更好的方法来做到这一点?还是只为更新日期时间的特定交易启用同步?

编辑(添加了有关我要执行的操作的更多详细信息):

我正在尝试从AddNewOrder.java调用此方法:

public void updateFields(String actionDateField) {
    Map<String, Object> updates = new HashMap<>();
    updates.put(actionDateField, FieldValue.serverTimestamp());
    updateSubmit.update(updates);
 }

来自(AddNewOrder.java)以外的班级:

db = new DatabaseHelper(getApplicationContext());
db.updateFields("OrderDate");
finish();

Finish();然后将我带回到上一个调用RecyclerView的活动:

      Query query = mFirestore
            .collection("Org")
            .document(RootCollection)
            .collection("Stores")
            .document(StoreID)
            .collection("Orders")
            .whereGreaterThan("OrderVerified", "")
            .limit(queryLimit);
      mAdapter = new OrdersAdapter(query, FulfilmentActivity.this) {
        @Override
        protected void onError(FirebaseFirestoreException e) {
            // Show a snackbar on errors
            Snackbar.make(findViewById(android.R.id.content),
                    "Error: check logs for info.", Snackbar.LENGTH_LONG).show();
        }
    };

    mAdapter.setQuery(query);
    mOrdersRecycler.setAdapter(mAdapter);


    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    mOrdersRecycler.setLayoutManager(layoutManager);

在OrdersAdapter.java中,我有这个:

  Orders orders = snapshot.toObject(Orders.class);
  submitDate.setText(FORMAT.format(orders.getOrderDate()));

public void bind中。

上面是NullPointerException出现的那一行。

Orders.java:

 public class Orders {
  private Timestamp OrderDate;
  public Orders(Timestamp orderDate) { this.OrderDate = orderDate; }
  public java.util.Date getOrderDate() { return OrderDate.toDate(); }
}

如何正确解决此问题?

2 个答案:

答案 0 :(得分:0)

首先,如果您正在使用线程处理Firestore,则几乎可以肯定是做错了。所有Firestore API(实际上是所有Firebase API)都是异步的,并且您的应用程序不需要线程。

Q1-使用时间戳创建的文档中没有中间的空值。服务器立即解释服务器时间戳记令牌,并自动将Timestamp对象写入文档。

第二季度-我真的无法告诉您您要使用此代码完成什么。这超出了您通常编写Firestore的范围。如果您想知道Firestore中的文档是否已更改,可以将侦听器附加到对该文档的引用,并在看到该文档发生更改时调用该侦听器。同样,在这种情况下不需要线程处理,因为回调都是异步的。只要添加了侦听器,它就会被调用。

答案 1 :(得分:0)

serverTimeStamp()实际上在从服务器获得确认响应之前在缓存中变为Null:https://github.com/firebase/firebase-js-sdk/issues/192

请参考此作为解决方案:https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/Document

我通过添加以下内容解决了此问题:

DocumentSnapshot.ServerTimestampBehavior behavior = ESTIMATE;
Date date = snapshot.getDate("OrderDate", behavior);