onClick仅在第二次或第三次点击后递增计数器(Firebase Transactions)

时间:2018-03-13 18:11:19

标签: java android firebase firebase-realtime-database transactions

问题

我将MutableData值变为null,直到我多次点击onClick(这对用户来说是不可行的)。

每次添加员工时,我都会尝试增加数据库中的员工数量值。我研究了交易并看到了以下内容(Firebase runTransaction not working)和(https://www.firebase.com/docs/android/guide/saving-data.html#section-transactions)并遵循了此文档。

使用调试程序重新创建问题的步骤

  1. 当它进入incrementNumEmp并进入doTransaction时 方法我在if上得到这个(注意在任何点击之前数据库中的起始值是3):
  2.   

    MutableData {key =,value = null}“

    1. 点击复选标记按钮(onClick)
    2. 我在调试器中单击“恢复程序”。它 从Transaction.success返回到if语句,现在它 有:
    3.   

      “MutableData {key =,value = 4}”

      数据库结构:

      enter image description here

      相关守则:

      private void incrementNumEmp(String compid) {
      
              Log.i("insideIncrementMethod", compid);
              mCompTotalEmpRef.child(compid).child("CompanyTime").child("TotalEmployees").runTransaction(new Transaction.Handler() {
                  @Override
                  public Transaction.Result doTransaction(MutableData mutableData) {
                      if(mutableData.getValue() !=null) {
                          mutableData.setValue((Long) mutableData.getValue() + 1);
                      }
                      return Transaction.success(mutableData);
                  }
      
                  @Override
                  public void onComplete(DatabaseError databaseError, boolean b,
                                         DataSnapshot dataSnapshot) {
                      Log.d("TAG", "countTransaction:onComplete:" + databaseError);
                  }
              });
          }
      

      代码的全部内容:

      public class RegisterEmployeeActivity extends Activity {
      
          EditText firstName, lastName, phoneNumber, emailET, ssnET, passwordET;
          String email, password, ssn, fName, lName, phone;
          String companyID;
          boolean fieldsFilled;
      
          private ImageView checkmarkImage;
          private FirebaseAuth auth;
          DatabaseReference mDatabase;
          FirebaseStorage storage;
          StorageReference storageReference;
      
          //PHOTO STUFF
          StorageMetadata metadata;
          UploadTask uploadTask;
          Uri file;
      
      
          private static FirebaseUser currentUser;
          String currentUserString;
          FirebaseDatabase database;
          DatabaseReference mDatabaseEmp, mDatabaseComp, mDatabaseUnverified;
          DatabaseReference mDatabseCompEmp;
          DatabaseReference mCompTotalEmpRef;
      
          //PHONE STUFF
          PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
          String mVerificationId;
          PhoneAuthProvider.ForceResendingToken mResendToken;
          FirebaseAuth mAuth;
      
      
          private FirebaseAuth.AuthStateListener mAuthListener;
      
          private FirebaseMethods firebaseMethods;
          private Context mContext;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_register_employee);
      
              firstName = (EditText) findViewById(R.id.firstNameET);
              lastName = (EditText) findViewById(R.id.lastNameET);
              phoneNumber = (EditText) findViewById(R.id.phoneET);
              emailET = (EditText) findViewById(R.id.emailET);
              ssnET = (EditText) findViewById(R.id.ssnET);
              passwordET = (EditText) findViewById(R.id.passwordET);
      
      
      
              //Get Firebase auth instance
              auth = FirebaseAuth.getInstance();
      
              //PHOTO STORAGE
              storage = FirebaseStorage.getInstance();
              storageReference = storage.getReferenceFromUrl("gs://timeclock-fc.appspot.com");
              //storageReference = storage.getReferenceFromUrl("gs://timeclock-fc.appspot.com").child("20170702_174811.jpeg"); //was PNG
      
              //FIREBASE METHODS
              mContext = RegisterEmployeeActivity.this;
              firebaseMethods = new FirebaseMethods(mContext);
      
              //DATABASE REFERENCES
              mDatabase = FirebaseDatabase.getInstance().getReference("/Unverified Employees");
              //Log.i("db ref", mDatabase.child("RC9zIioE6vc5vlhrIethmbqyFDS2").getKey());
              database = FirebaseDatabase.getInstance();
              mDatabaseEmp = database.getReference("/Employees");
              mDatabaseComp = database.getReference("/Companies");
              mDatabaseUnverified = database.getReference("/Unverified Employees");
              mDatabseCompEmp = database.getReference("/CompanyEmployees/CompanyIDs");
              mCompTotalEmpRef = database.getReference("/CompanyEmployeeTime/CompanyIDs");
      
              currentUser =
                      FirebaseAuth.getInstance().getCurrentUser();
      
      
               mAuth = FirebaseAuth.getInstance();
      
      
              //final ImageView checkmarkImage = (ImageView) findViewById(R.id.checkmarkImage);
              checkmarkImage = (ImageView) findViewById(R.id.checkmarkImage);
      
              //Insert information into FirebaseDB and go to next screen
              checkmarkImage.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(final View view) {
                  //public void onClick(View view) {
      
                      //Assigns EditText values to String values
                      assignStringValues();
      
      
                      //Ensures that EditText fields are filled. If not will give a warning
                      fieldsFilled = areFieldsFilled();
      
                      mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
                          @Override
                          public void onDataChange(DataSnapshot dataSnapshot) {
      
                              Log.i("DATA VALUE", dataSnapshot.child("RC9zIioE6vc5vlhrIethmbqyFDS2").getValue().toString());
      
                              //Used https://github.com/mitchtabian/Android-Instagram-Clone/tree/6e2ffe29621c592e57057b8561d3cac4df9c14a1/app/src/main/java/tabian/com/instagramclone  and https://www.youtube.com/watch?v=I-2T4i75gfw
      
      
                              Log.i("EMAIL NULL?", email);
                              Log.i("SSN", ssn);
                              Log.i("ds/Input", dataSnapshot.toString());
                              companyID = firebaseMethods.checkIfSsnExists(ssn, dataSnapshot);
                              //Log.i("companyIDRegister", companyID);
                              if(email!= null && !email.equals("")) {
                                  //CHECK IF IT MATCHES (SSN) *AND* Email
                                  //companyID = firebaseMethods.checkIfSsnExists(ssn, dataSnapshot);
                                  if (firebaseMethods.checkIfEmailExists(email, dataSnapshot) && companyID.length()>0) {
      
                                      //if (firebaseMethods.checkIfEmailExists(email, dataSnapshot) && firebaseMethods.checkIfSsnExists(ssn, dataSnapshot)) {
                                      auth.createUserWithEmailAndPassword(emailET.getText().toString(), passwordET.getText().toString())
                                              .addOnCompleteListener(RegisterEmployeeActivity.this, new OnCompleteListener() {
                                                  @Override
                                                  public void onComplete(@NonNull Task task) {
                                                      //progressBar.setVisibility(View.GONE);
                                                      if (!task.isSuccessful()) {
                                                          //EXCEPTION MESSAGES
                                                          try {
                                                              throw task.getException();
                                                          } catch (FirebaseAuthWeakPasswordException e) {
                                                              MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "Password should be atleast 6 characters");
                                                          } catch (FirebaseAuthInvalidCredentialsException e) {
                                                              MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "The email address is badly formatted");
                                                          } catch (FirebaseAuthUserCollisionException e) {
                                                              MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "The email address is already in use by another account");
      
                                                          } catch (Exception e) {
                                                              e.printStackTrace();
                                                          }
      
                                                      } else {
      
                                                          //SEND INFORMATION TO FIREBASE DATABASE
                                                          //companyID = firebaseMethods.getCompanyID();
                                                          //addEmployeeToFirebase(currentUser);
                                                          currentUser =
                                                                  FirebaseAuth.getInstance().getCurrentUser();
                                                          Log.i("beforeAddEmail",currentUser.getUid());
                                                          addEmployeeToFirebase(currentUser, companyID);
                                                          removeEmail();
      
      
                                                          /*if(fieldsFilled == true) {
                                                              startActivity(new Intent(RegisterEmployeeActivity.this, EmployeeHome.class));
                                                              finish();
                                                          } */
      
                                                      }
                                                  } //END OF ONCOMPLETE
                                              }); //END OF ONCOMPLETELISTENER
                                  } //END OF (IF) CHECKEMAILEXISTS
                                  else {
                                      MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "You must use the email and ssn your employer has entered");
                                  }
                              }  //END OF EMAIL CHECK
      
                              //PHONE # CHECK
                              if(phone != null && !phone.equals("")) {
                                  //CHECK IF SSN *AND* PHONE EXISTS
                                  //companyID.length()>0
                                  if (firebaseMethods.checkIfPhoneExists(phone, dataSnapshot) && companyID.length()>0) {
      
                                      //if (firebaseMethods.checkIfPhoneExists(phone, dataSnapshot) && firebaseMethods.checkIfSsnExists(ssn, dataSnapshot)) {
      
      
                                      Log.i("IF", "INSIDE IF");
                                      mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
      
                                          //USING https://github.com/firebase/quickstart-android/blob/master/auth/app/src/main/java/com/google/firebase/quickstart/auth/PhoneAuthActivity.java
      // Originally https://firebase.google.com/docs/auth/android/phone-auth
                                          @Override
                                          public void onVerificationCompleted(PhoneAuthCredential credential) {
                                              // This callback will be invoked in two situations:
                                              // 1 - Instant verification. In some cases the phone number can be instantly
                                              //     verified without needing to send or enter a verification code.
                                              // 2 - Auto-retrieval. On some devices Google Play services can automatically
                                              //     detect the incoming verification SMS and perform verification without
                                              //     user action.
                                              Log.i("VERIFICATION_COMPLETED", "onVerificationCompleted:" + credential);
      
                                              //unnecessary?
                                              // [START_EXCLUDE silent]
                                              //mVerificationInProgress = false;
                                              // [END_EXCLUDE]
      
                                              // [START_EXCLUDE silent]
                                              // Update the UI and attempt sign in with the phone credential
                                              //updateUI(STATE_VERIFY_SUCCESS, credential);
                                              // [END_EXCLUDE]
                                              //TODO: See why this is no longer called
                                              signInWithPhoneAuthCredential(credential);
                                          }
      
      
                                          @Override
                                          public void onVerificationFailed(FirebaseException e) {
                                              // This callback is invoked in an invalid request for verification is made,
                                              // for instance if the the phone number format is not valid.
                                              Log.i("VERIFICATION_FAILED", "onVerificationFailed", e);
      
                                              if (e instanceof FirebaseAuthInvalidCredentialsException) {
                                                  // Invalid request
                                              } else if (e instanceof FirebaseTooManyRequestsException) {
                                                  // The SMS quota for the project has been exceeded
                                              }
      
                                              // Show a message and update the UI
                                          }
      
                                          //Looks Good
                                          @Override
                                          public void onCodeSent(String verificationId,
                                                                 PhoneAuthProvider.ForceResendingToken token) {
                                              // The SMS verification code has been sent to the provided phone number, we
                                              // now need to ask the user to enter the code and then construct a credential
                                              // by combining the code with a verification ID.
                                              Log.i("CODE_SENT", "onCodeSent:" + verificationId);
      
                                              // Save verification ID and resending token so we can use them later
                                              mVerificationId = verificationId;
                                              mResendToken = token;
                                              //PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, mResendToken);
      
                                              // ...
                                          }
      
                                      }; //END OF MCALLBACKS
      
      
      
                                  verifyPhone(phone, mCallbacks);
      
      
                                          } //END OF (IF) CHECK IF PHONE EXISTS
                                  else {
                                      MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "You must use the phone number and ssn your employer has entered");
      
                                  }
                              }  //END OF PHONE# Check
                          } //END OF ONDATACHANGE
      
                          @Override
                          public void onCancelled(DatabaseError databaseError) {
                          } //CLOSE ONCANCELLED
      
                      }); //END OF mDatabase Listener
      
                      // } //END OF ONAUTHSTATECHANGED
                      // }; //END OF FIREBASE AUTH STATE LISTENER
                  } //END OF ONCLICK
              }); //END OF CHECKMARK
      
      
          }  //END OF ONCREATE
      
          private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
              //Log.i("mAuth", mAuth.toString());
              //FirebaseAuth.getInstance().signInWithCredential(credential)
              mAuth.signInWithCredential(credential)
                      .addOnCompleteListener(RegisterEmployeeActivity.this, new OnCompleteListener<AuthResult>() {
                          @Override
                          public void onComplete(@NonNull Task<AuthResult> task) {
                              if (task.isSuccessful()) {
                                  // Sign in success, update UI with the signed-in user's information
                                  Log.i("SIGNINWITHCREDENTIAL", "signInWithCredential:success");
      
                                  FirebaseUser user = task.getResult().getUser();
                                  // ...
                              }
      
                              else {
                                  // Sign in failed, display a message and update the UI
                                  Log.i("SIGNINWITHCREDENTIAL", "signInWithCredential:failure", task.getException());
                                  if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                                      // The verification code entered was invalid
                                  }
                              }
      
                              assignStringValues();
      
                              currentUser =
                                      FirebaseAuth.getInstance().getCurrentUser();
      
                              //SEND INFORMATION TO FIREBASE DATABASE
                              companyID = firebaseMethods.getCompanyID();
                              Log.i("companyID", companyID);
                              addEmployeeToFirebase(currentUser, companyID);
                              //     addEmployeeToFirebase(currentUser);
      
      
                              Log.i("fieldsFilled", String.valueOf(fieldsFilled));
                              if(fieldsFilled == true) {
                                  finish();
                                  startActivity(new Intent(RegisterEmployeeActivity.this, EmployeeHome.class));
                                  //finish();
                              }
      
                          } //End of OnComplete
                      });
          }
      
          //PhoneAuthProvider.OnVerificationStateChangedCallbacks()
          public void verifyPhone(String phone, PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks)
          {
              PhoneAuthProvider.getInstance().verifyPhoneNumber(
                      phone,        // Phone number to verify
                      120,                 // Timeout duration
                      TimeUnit.SECONDS,   // Unit of timeout
                      RegisterEmployeeActivity.this,               // Activity (for callback binding)
                      mCallbacks);        // OnVerificationStateChangedCallbacks
          }
      
          DatabaseReference.CompletionListener completionListener =
                  new DatabaseReference.CompletionListener() {
                      @Override
                      public void onComplete(DatabaseError databaseError,
                                             DatabaseReference databaseReference) {
      
                          if (databaseError != null) {
                              notifyUser(databaseError.getMessage());
                          }
                      }
                  };
      
          private void notifyUser(String message) {
              Toast.makeText(RegisterEmployeeActivity.this, message,
                      Toast.LENGTH_SHORT).show();
          }
      
          private void assignStringValues() {
              email = emailET.getText().toString().trim();
              password = passwordET.getText().toString().trim();
              ssn = ssnET.getText().toString().trim();
              fName = firstName.getText().toString().trim();
              lName = lastName.getText().toString().trim();
              phone = phoneNumber.getText().toString().trim();
          }
      
          private boolean areFieldsFilled() {
      
      
              fieldsFilled = true;
              if (TextUtils.isEmpty(fName)) {
                  MethodHelper.showAlert(RegisterEmployeeActivity.this, "First Name Required", "A First Name is required. Please enter your name and try again.");
                  fieldsFilled = false;
      
              }
      
      
              if (TextUtils.isEmpty(lName)) {
                  MethodHelper.showAlert(RegisterEmployeeActivity.this, "Last Name Required", "A Last Name is required. Please enter your name and try again.");
                  fieldsFilled = false;
              }
      
      
              if ( (TextUtils.isEmpty(phone)) && TextUtils.isEmpty(email)) {
                  MethodHelper.showAlert(RegisterEmployeeActivity.this, "Phone Number OR Email Required", "A Phone Number OR Email is required. Please enter your number OR email and try again.");
                  fieldsFilled = false;
              }
      
      
              if (TextUtils.isEmpty(password)) {
                  MethodHelper.showAlert(RegisterEmployeeActivity.this, "Password Required", "A password is required. Please enter your password and try again.");
                  fieldsFilled = false;
              }
      
      
              if(TextUtils.isEmpty(ssn)) {
                  MethodHelper.showAlert(RegisterEmployeeActivity.this, "Social Security Number Required", "A social security number is required. Please enter the last 4 digits of your social security number and try again.");
                  fieldsFilled = false;
              }
              return fieldsFilled;
      
          }
      
          private void addEmployeeToFirebase(FirebaseUser currentUser, final String compid) {
              //SEND INFORMATION TO FIREBASE DATABASE
      
              // mDatabaseEmp.child(currentUser.getUid()).child("firstName")
              //        .setValue(fName, completionListener);
              //May want to set currentUser.getUid()) to a String?
      
              Log.i("addEmployeeToFirebase", "inside method");
      
              currentUserString = currentUser.getUid();
              Log.i("currentUserStringADDEMP", currentUserString);
              mDatabaseEmp.child(currentUserString).child("firstName")
                      .setValue(fName, completionListener);
              mDatabaseEmp.child(currentUserString).child("lastName")
                      .setValue(lName, completionListener);
              mDatabaseEmp.child(currentUserString).child("phoneNumber")
                      .setValue(phone, completionListener);
              mDatabaseEmp.child(currentUserString).child("email")
                      .setValue(email, completionListener);
              mDatabaseEmp.child(currentUserString).child("ssn")
                      .setValue(ssn, completionListener);
              Log.i("addEmp-CompID?", compid);
              mDatabaseEmp.child(currentUserString).child("CompanyID").setValue(compid, completionListener);
              mDatabseCompEmp.child(compid).child("EmployeeIDs").child(currentUserString).child("ID").setValue(currentUserString);
              //INCREMENT Total # Employees
              /*mCompTotalEmpRef.child(compid).child("CompanyTime").addValueEventListener(new ValueEventListener() {
                  @Override
                  public void onDataChange(DataSnapshot dataSnapshot) {
                      try {
      
                          long total = Long.parseLong(dataSnapshot.child("TotalEmployees").getValue().toString());
                          total = total + 1;
                          mCompTotalEmpRef.child(compid).child("CompanyTime").child("TotalEmployees").setValue(total);
                      }
                      catch (Exception e) {  Log.i("LNull?", e.toString());     }
                  }
      
                  @Override
                  public void onCancelled(DatabaseError databaseError) {   Log.d("Cancelled",databaseError.toString());     }
              }); */
      
      
              incrementNumEmp(compid);
      
      
          }
      
          private void incrementNumEmp(String compid) {
      
              Log.i("insideIncrementMethod", compid);
              mCompTotalEmpRef.child(compid).child("CompanyTime").child("TotalEmployees").runTransaction(new Transaction.Handler() {
                  @Override
                  public Transaction.Result doTransaction(MutableData mutableData) {
                      //long total = Long.parseLong(mutableData.getValue().toString()); //why is mutable data key none value null??
                     /* long total = 0;
                      if(mutableData.getValue(Long.class) != null) {
                          String numEmp = (String) mutableData.getValue();
                          //total = Long.parseLong(numEmp);
                          total = Long.parseLong(numEmp, 16);
      
                      } */
      
                      if(mutableData.getValue() !=null) {
                          mutableData.setValue((Long) mutableData.getValue() + 1);
                      }
                      //total = mutableData.getValue(Long.class);
      
                     /* Log.i("totalBefore", String.valueOf(total));
                      total++;
                      Log.i("totalAfter", String.valueOf(total));
                      String incHex = Long.toHexString(total); */
      
                      //mutableData.setValue(total);
                      //mutableData.setValue(incHex);
                      return Transaction.success(mutableData);
                  }
      
                  @Override
                  public void onComplete(DatabaseError databaseError, boolean b,
                                         DataSnapshot dataSnapshot) {
                      Log.d("TAG", "countTransaction:onComplete:" + databaseError);
                  }
              });
          }
      
          private void removeEmail() {
              /*Query emailQuery = mDatabase.child("emailAddress").equalTo(email);
              Log.i("emailRemove", email);
              Log.i("removeEmail","Inside");
              //mDatabaseEmp.child("emailAddress").equalTo(email).setValue("");
      
              //mDatabaseUnverified.child("emailAddress").equalTo(email).removeEventListener();
              emailQuery.addListenerForSingleValueEvent(new ValueEventListener() {
                  @Override
                  public void onDataChange(DataSnapshot dataSnapshot) {
                      for (DataSnapshot emailSnapshot: dataSnapshot.getChildren()) {
                          Log.i("snapshot", emailSnapshot.toString());
                          Log.i("snapshotRef", emailSnapshot.getRef().toString());
                          emailSnapshot.getRef().removeValue();
      
                      }
                  }
      
                  @Override
                  public void onCancelled(DatabaseError databaseError) {
                      Log.e("TAG", "onCancelled", databaseError.toException());
                  }
              }); */
      
      
              /*Query queryRef = mDatabase.orderByChild("Unverified Employees").equalTo(email);
      
              queryRef.addChildEventListener(new ChildEventListener() {
                  @Override
                  public void onChildAdded(DataSnapshot snapshot, String previousChild) {
                      Log.i("snapshot", snapshot.toString());
                      Log.i("snapshotRef", snapshot.getRef().toString());
                      snapshot.getRef().setValue(null);
                  }
      
                  @Override
                  public void onChildRemoved(DataSnapshot snapshot) {
                      Log.e("TAG","onChildRemoved "+ snapshot.toString());
                  }
      
                  @Override
                  public void onCancelled(DatabaseError databaseError) {
      
                  }
      
                  @Override
                  public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                      Log.e("TAG","onChildChanged "+ dataSnapshot.toString()+" \n String "+s);
                  }
      
                  @Override
                  public void onChildMoved(DataSnapshot dataSnapshot, String s) {
                      Log.e("TAG","onChildAdded "+ dataSnapshot.toString()+" \n String "+s);
                  }
      
              }); */
      
              Query emailQuery = mDatabase.child("emailAddress").equalTo(email);
      
              emailQuery.addListenerForSingleValueEvent(new ValueEventListener() {
                  @Override
                  public void onDataChange(DataSnapshot dataSnapshot) {
                      for (DataSnapshot emailSnapshot: dataSnapshot.getChildren()) {
                          Log.i("snapshot", emailSnapshot.toString());
                          Log.i("snapshotRef", emailSnapshot.getRef().toString());
                          emailSnapshot.getRef().removeValue();
                      }
                  }
      
                  @Override
                  public void onCancelled(DatabaseError databaseError) {
                      Log.e("TAG", "onCancelled", databaseError.toException());
                  }
              });
          }
      
      
      
      }
      

1 个答案:

答案 0 :(得分:0)

因此,在添加了更多日志语句之后,似乎我的“finish()”出现在了错误的位置。由于DB Listener是异步的,因此必须在Transactions可变之前调用finish。

我最初拥有的DB​​ Listener内部:

addEmployeeToFirebase(currentUser, companyID);
finish();

我将其更改为以下内容,现在可以正常使用!:

finish();
addEmployeeToFirebase(currentUser, companyID);

对我来说奇怪的是另一个.setValues工作正常,但对于Transaction mutableData我必须在它之前完成