我使用的是Android,我想在Firebase实时数据库中存储一些数据。奇怪的是,有时这种方法有效,有时却无效。我认为这可能与我的WLAN连接有关,但WLAN连接并不总是很好,但即使WLAN连接很好,有时数据也可以写入Firebase数据库,有时它就是不起作用。
不管怎样,如果是这种情况,我希望以toast的形式向用户传达一条消息,即数据尚未写入Firebase数据库。为此,我有以下Java片段:
package com.example.td.bapp;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.Navigation;
import com.example.td.bapp.databinding.TestFragmentBinding ;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
public class TestFragment extends Fragment implements View.OnClickListener {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
private TestFragmentBinding binding;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = TestFragmentBinding.inflate(inflater, container, false);
/*
Set onClickListeners to the buttoms
*/
binding.orderingButton.setOnClickListener(this);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onClick(View view) {
if(view.getId() == R.id.ordering_button) {
/*
Write data into the Firebase DB
*/
long currentTimeMillis = System.currentTimeMillis();
SimpleDateFormat sdf1 = new SimpleDateFormat("dd-MM-yy");
sdf1.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
SimpleDateFormat sdf2 = new SimpleDateFormat("HH-mm-ss");
sdf1.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
DatabaseReference rootRef = FirebaseDatabase.getInstance("https://drink-server-db-default-rtdb.europe-west1.firebasedatabase.app").getReference();
DatabaseReference ordersRef = rootRef.child("orders");
String id ="table_" + MainActivity.tableNumber + "_order_" + MainActivity.orderNumberOfTheSession + "_date_" + sdf1.format(new Date()) + "_time_" + sdf2.format(new Date());
String name1 = "Test_1";
String name2 = "Test_2";
FirebaseDBItem_Order currentOrder = new FirebaseDBItem_Order(name1, name2);
Log.e("LogTag", "Before write into DB");
ordersRef.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.e("dbTAG", "Data successfully written.");
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedSuccessfully), duration);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
else {
Log.e("dbTAG", task.getException().getMessage());
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedNotSuccessfully), duration);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("LogTag", "After write into DB");
Navigation.findNavController(getView()).navigate(TestFragmentDirections.actionFRCocktailToFRMenu());
}
}
}
如果数据成功写入Firebase数据库,则显示toast,并且我得到正确的dbTAG和LogTag消息:
E/LogTag:写入数据库之前
E/LogTag:写入数据库后
E/dbTAG:数据写入成功。
然而,当数据没有成功写入Firebase数据库时,我只是没有从onComplete方法的dbTAG中得到任何消息,并且在数据库中找不到新的条目。我刚刚收到LogTag消息:
E/LogTag:写入数据库之前
E/LogTag:写入数据库后
现在实际上我有两个问题:
- 为什么有时数据可以写入Firebase数据库,有时却不能,以及为什么这种情况似乎会发生"随机地";?你能想出一些原因吗
- 更重要的是:当数据无法写入Firebase数据库时,我如何获得错误消息,以便通知用户?与此相关的是:当数据没有成功写入Firebase数据库时,为什么我没有收到
Log.e("dbTAG", task.getException().getMessage());
消息?因此,当数据未成功存储时,不执行onComplete
方法的else分支
如果您需要任何进一步的信息,请告诉我。
为什么有时数据可以写入Firebase数据库,有时却不能,以及为什么会发生这种情况"随机地";?你能想出一些原因吗?
这很可能是因为缺乏互联网连接。要解决此问题,您应该启用脱机持久性。在Java代码中,这可以使用以下行来完成:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
根据文件:
Firebase应用程序即使您的应用程序暂时失去网络连接也能正常工作。
Firebase应用程序自动处理临时网络中断。缓存数据在脱机时可用,Firebase在恢复网络连接时重新发送任何写入。
然后回答您的第二个问题:
更重要的是:当数据无法写入Firebase数据库时,我如何获得错误消息,以便通知用户?与此相关的是:为什么我没有得到一个Log.e("dbTAG",task.getException((.getMessage(((;当数据未成功写入Firebase数据库时,是否显示消息?因此,当数据未成功存储时,onComplete方法的else分支不会执行。
您正在使用以正确的方式处理错误
Log.e("dbTAG", task.getException().getMessage());
当写入数据出现问题时,您会收到一条错误消息,这意味着写入操作被Firebase服务器拒绝,例如,当您有不正确的安全规则时。
还请注意,当没有互联网连接时,Firebase实时数据库SDK不会抛出异常,这是有道理的,因为Firebase实时数据库是为离线工作而设计的。在幕后,Firebase实时数据库SDK会尝试重新连接,直到设备恢复连接。然而,当Firebase服务器由于安全规则问题拒绝请求时,它确实会抛出异常。