Android - Firebase - 从节点X检索数据并将其发送到节点Y.

时间:2017-09-25 12:14:45

标签: java android firebase firebase-realtime-database

目标

允许用户向当局发送报告。报告将被存储,并且在同一用户输入新报告时不会被覆盖

当前数据库的图片

enter image description here

当前登录的用户能够将“事件报告”存储到数据库中,但显然当用户提交另一个“事件报告”时,新提交的“事件报告”将覆盖先前“事件报告”的数据< / p>

所需数据库的图片

enter image description here

黄色突出显示的数据应该是从“用户”子项“名称”中检索的数据,该名称是红色圆圈数据

例如,如果红色圆圈数据中的数据为“Abe Long”,则黄色突出显示的数据也将为“Abe Long”。 / p>

除此之外,当用户签名的当前提交“事件报告”时,创建的每个新事件都将创建一个新的唯一密钥。这意味着它不会覆盖以前提交的数据。

报告片段类

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.util.Date;
import java.util.HashMap;


public class ReportFragment extends Fragment {

    private EditText jReportDatePick;
    private EditText jReportTimeEnt;
    private EditText jReportLocationEnt;
    private EditText jReportDescriptionEnt;

    private Button jReportSendBtn;

    private FirebaseUser jReportCurrentUserID;

    private DatabaseReference jReportByUserDatabase;

    private ProgressDialog jReportLoad;

    public ReportFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View viewRoot = inflater.inflate(R.layout.fragment_report, container, false);

        jReportDatePick = viewRoot.findViewById(R.id.reportDatePick);
        jReportTimeEnt = viewRoot.findViewById(R.id.reportTimeEnt);
        jReportLocationEnt = viewRoot.findViewById(R.id.reportLocationEnt);
        jReportDescriptionEnt = viewRoot.findViewById(R.id.reportDescriptionEnt);

        jReportSendBtn = viewRoot.findViewById(R.id.reportSendBtn);

        jReportLoad = new ProgressDialog(getActivity());

        jReportSendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String userReportDate = jReportDatePick.getText().toString();
                String userReportTime = jReportTimeEnt.getText().toString();
                String userReportLocation = jReportLocationEnt.getText().toString();
                String userReportDescription = jReportDescriptionEnt.getText().toString();

                if(!TextUtils.isEmpty(userReportDate)&&
                        !TextUtils.isEmpty(userReportTime)&&
                        !TextUtils.isEmpty(userReportLocation)&&
                        !TextUtils.isEmpty(userReportDescription)){
                    submitReport(userReportDate, userReportTime, userReportLocation, userReportDescription);
                    jReportLoad.setTitle("Sending Report");
                    jReportLoad.setMessage("Please wait while the report is being sent");
                    jReportLoad.setCanceledOnTouchOutside(false);
                    jReportLoad.show();
                }else{
                    jReportLoad.dismiss();
                    Toast.makeText(getActivity(), "Report failed to be sent due to empty inputs", Toast.LENGTH_SHORT).show();
                }

            }
        });

        return  viewRoot;
    }

    private void submitReport(final String userReportDate,final String userReportTime,
                              final String userReportLocation,final String userReportDescription) {

        jReportCurrentUserID = FirebaseAuth.getInstance().getCurrentUser();
        final String reportUserID = jReportCurrentUserID.getUid();
        jReportByUserDatabase = FirebaseDatabase.getInstance().getReference().child("Incident Reports").child(reportUserID);

        HashMap<String, String> incidentReportUser = new HashMap<>();
        incidentReportUser.put("date", userReportDate);
        incidentReportUser.put("time", userReportTime);
        incidentReportUser.put("location", userReportLocation);
        incidentReportUser.put("description", userReportDescription);

        jReportByUserDatabase.setValue(incidentReportUser).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if(task.isSuccessful()){
                    jReportLoad.dismiss();
                    Toast.makeText(getActivity(), "Report was Sent", Toast.LENGTH_SHORT).show();
                    jReportDatePick.setText("");
                    jReportTimeEnt.setText("");
                    jReportLocationEnt.setText("");
                    jReportDescriptionEnt.setText("");
                }else{
                    jReportLoad.dismiss();
                    Toast.makeText(getActivity(), "Report failed to be sent", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

其他评论

  • 报告片段的工作原理

我不打算让当前登录的用户能够提交他们的名字,这将使用户在“事故报告”中输入其他人的姓名。我打算检索“CurrentUser登录”名称并自动输入“事故报告”。

  • 报告片段的编码方式

而不是jReportByUserDatabase.setValue(incidentReportUser)我尝试在使用.updateChildren时放置Map<String, Object>。问题是每个数据在“唯一ID”下输入,该ID将存储在数据树中的“事件报告”下

解决问题的方法

  

由Cadet和JavaBanana协助

实现“For Loop DataSnapshot”以循环访问数据并通过使用包含名称,地址,状态等的“Users class”来检索所需的数据。

private void submitReport(final String userReportDate,final String userReportTime,
                          final String userReportLocation,final String userReportDescription) {

DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
dbRef.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
            Users user = snapshot.getValue(Users.class);
            HashMap<String, String> incidentReportUser = new HashMap<>();
            incidentReportUser.put("name", user.name);
            incidentReportUser.put("date", userReportDate);
            incidentReportUser.put("time", userReportTime);
            incidentReportUser.put("location", userReportLocation);
            incidentReportUser.put("description", userReportDescription);

            jReportCurrentUserID = FirebaseAuth.getInstance().getCurrentUser();
            final String reportUserID = jReportCurrentUserID.getUid();
            jReportByUserDatabase = FirebaseDatabase.getInstance().getReference().child("Incident Reports").child(reportUserID);
            jReportByUserDatabase.push().setValue(incidentReportUser).addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if(task.isSuccessful()){
                        jReportLoad.dismiss();
                        Toast.makeText(getActivity(), "Report was Sent", Toast.LENGTH_SHORT).show();
                        jReportDatePick.setText("");
                        jReportTimeEnt.setText("");
                        jReportLocationEnt.setText("");
                        jReportDescriptionEnt.setText("");
                    }else{
                        jReportLoad.dismiss();
                        Toast.makeText(getActivity(), "Report failed to be sent", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
    @Override
    public void onCancelled(DatabaseError databaseError) {
    }
});
}

2 个答案:

答案 0 :(得分:2)

通过这种方式写出来 (Push会添加值,而不是覆盖)。

jReportByUserDatabase.push()setValue(incidentReportUser)

另外,我建议也让Report节点包含用户字段。比如将它们组合成扁平节点。

enter image description here

答案 1 :(得分:1)

好的,你的设计的主要问题是你将报告存储在用户的ID下,哪个firebase会明显覆盖。

您可以生成用于存储报告的随机密钥,并将报告设置为数据库中生成的密钥。

public class Report {
  String reportId; // This is important
  String reporterId;  //This is important
  String reporterName;
  String userType;
  String status;
  String address;
  String neibourhood;
  String image;
}

DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference("Incident Reports");
String reportId = dbRef.push().getKey(); //This generates a new key and returns it
Report report = new Report("report id", "reporter id", "other stuff"... "etc");
dbRef.child(reportId).setValue(report);

检索用户名

DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
dbRef.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        //Loop through the retrieved user data
        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
            User user = snapshot.getValue(User.class);
            System.out.println(user.name);
        }
    }
    @Override
    public void onCancelled(DatabaseError databaseError) {}
});