gpt4 book ai didi

java - Firebase onChildRemoved() 和 removeValue() 处理时间敏感操作的问题

转载 作者:行者123 更新时间:2023-11-29 18:50:29 25 4
gpt4 key购买 nike

我有一个应用程序可以提供一些东西。我的想法是,优惠由我添加到我创建的另一个应用程序中,然后同时显示在用户设备上。

我只需要一个用户就可以接受报价,因此当第一个用户点击时,我会在报价引用上调用 removeValue()。该优惠已从数据库和其他用户 recyclerview 中正确删除。

问题是当 2 次点击同时发生时,报价被删除但 onChildRemoved() 没有时间被调用,所以两个用户现在有相同的报价!

是否有任何其他想法如何使此操作更精确和时间感知?

UPDATE 根据 svi.data 的建议,我在用户点击时尝试了这段代码,但仍然出现同样的问题。

    offerUnAnsweredRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

boolean stillThere = false;

for (DataSnapshot offerSnap : dataSnapshot.getChildren()) {

if (offerSnap.getKey().equals(requestedOffer.getCurrentNodeKey())) {
stillThere = true;
}
}

if (stillThere) {
Timber.d("We have it " + requestedOffer.getEmployeeKey());
Toast.makeText(getContext(), "Welcome Dear ", Toast.LENGTH_SHORT).show();
offerUnAnsweredRef.child(requestedOffer.getCurrentNodeKey()).removeValue();
} else {
Toast.makeText(getContext(), "Go Away Bear", Toast.LENGTH_SHORT).show();

}
}

@Override
public void onCancelled(@NonNull DatabaseError databaseError) {

}
});

更新 2

实际上,该解决方案是在 svi.data 答案之上构建的,并进行了一些修改,所以我想分享工作代码,以帮助遇到类似情况的人

offerUnAnsweredRef.child(requestedOffer.getCurrentNodeKey()).runTransaction(new Transaction.Handler() {
@NonNull
@Override
public Transaction.Result doTransaction(@NonNull MutableData mutableData) {


RequestedOffer o = mutableData.getValue(RequestedOffer.class);
if (o == null) {
return Transaction.abort();
}

if (o.getEmployeeKey() == null) {
o.setEmployeeKey(employee.getUid());
mutableData.setValue(o);
return Transaction.success(mutableData);

} else {
return Transaction.success(mutableData);
}
}

@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// check if the transaction completed successfully
// or if it failed
RequestedOffer o = dataSnapshot.getValue(RequestedOffer.class);
if (o.getEmployeeKey() == employee.getUid()) {
getActivity().runOnUiThread(() -> Toast.makeText(getActivity(), "Hello", Toast.LENGTH_SHORT).show());
DatabaseReference databaseReference = FirebaseFactory.getDatabase()


} else {
getActivity().runOnUiThread(() -> Toast.makeText(getActivity(), "NO", Toast.LENGTH_SHORT).show());
}
}

因为正如文档所说

public abstract Transaction.Result doTransaction (MutableData currentData)

This method will be called, possibly multiple times, with the current data at this location. It is responsible for inspecting that data and returning a Transaction.Result specifying either the desired new data at the location or that the transaction should be aborted.

所以我添加了代码来检查 onComplete 以确保它只调用一次。

最佳答案

据我了解:

1) 你有一个特定的应用程序来添加优惠(由你)。

2) 您有另一个用于阅读报价(用户)的应用程序。

3) 如果是这种情况,则两个应用程序使用相同的项目。

4) 当用户点击报价时,他/她将获得报价,然后您将从数据库中删除报价。

5) 现在,当 2 个用户点击相同的报价时,没有时间将该报价从其他用户的列表中删除,因此他们最终得到相同的报价。

现在看来你不想让用户获得相同的优惠,问题确实是时间问题。

可能的解决方案:

1) 当用户点击一个报价时,您将对数据库中的 offers 节点运行 ValueEventListener() 并检查报价是否存在。

2) 如果报价存在,给他/她报价并删除它。

3) 现在,当 2 个用户单击同一个报价时,我谈到的 ValueEventListener 会在您使用react之前为您提供一些时间。

4) 所以用户不应该得到相同的优惠。

希望它能解决您的问题。

更新:

由于这是用户之间的竞争条件,现在是时候讨论交易了。 Firebase 提供了一种直接读取和写入同一节点(您的情况)的并发更新的好方法。

我希望你的数据库是这样的:

Offers
|
|------offer_id_1
|
|-----taken:false
|-----......
|-----......
|
|-------offer_id_2
|
|------taken:false
|------......
|------......

让我解释一下上面的结构,您从其他应用程序发布的每个优惠默认情况下都会有一个名为 taken 的标志,默认情况下它的值应该是 false .

现在如上所示,offer_id_1offer_id_2 是为优惠提供的推送 ID 或随机 ID(当用户点击优惠时,您必须获得引用这把 key ....我假设你知道如何做到这一点)。

当然,在我们开始之前,您应该为您的帖子创建一个模型类,我们将其称为Offer,它只是一个类:

public class Offer{

public boolean taken;
......
......


}

以下函数是您在有人点击报价后调用的函数(我们将使用交易):

public void RunTransactionFor(String offer_id){


//first refer to your offers
DatabaseReference offers_ref = FirebaseDatabase.getInstance().getReference().child("offers").child(offer_id);

//run a transaction (a transaction is fast it reads and writes directly)

offer_ref.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
//this is a ref to the offer class
Offer offer = mutableData.getValue(Offer.class);

if (offer == null) {
return Transaction.success(mutableData);
}
if(offer.taken == false){
//take the offer
offer.taken = true;
//show a message
Toast.makeText(context, "you took the offer",...).show();
//now you can remove the offer
offers_ref.setValue(null);//or delete it your way



}else{
//too late the offer is taken
Toast.makeText(context, "too late the offer is gone",...).show();
//do nothing
}

// Set value and report transaction success
mutableData.setValue(offer);
return Transaction.success(mutableData);
}

@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed

}
});

}

现在,当用户单击列表中的报价时,存储报价的 ID 并将其传递给上述函数,如下所示

//after user clicks

String offer_id = .......

//run transaction

RunTransactionFor(offer_id);

注意:交易只能在线进行,不能离线进行。

关于java - Firebase onChildRemoved() 和 removeValue() 处理时间敏感操作的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51012458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com