调用batch.commit
或docRef.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(); }
}
如何正确解决此问题?
答案 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);