How does Firebase sync work, with shared data?

后端 未结 3 1221
时光取名叫无心
时光取名叫无心 2020-12-11 07:44

I use Firebase to handle the Auth topic of my Android app. I also save a user profile on Firebase, that contain user id and extra options that user can update in the android

3条回答
  •  佛祖请我去吃肉
    2020-12-11 08:29

    To bring the (1) solution from @frank-van-puffelen into code :

    public class MainActivity extends AppCompatActivity {
    
        Firebase ref;
        User user;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ref = new Firebase("https://test.firebaseIO.com").child("user");
            ref.keepSynced(true);
    
            Button br = (Button) findViewById(R.id.b_read);
            Button bs = (Button) findViewById(R.id.b_save);
            final TextView tv_r = (TextView) findViewById(R.id.tv_value_toread);
            final EditText tv_s = (EditText) findViewById(R.id.tv_value_tosave);
    
            user = new User();
    
            bs.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!tv_s.getText().toString().equalsIgnoreCase(""))
                        user.setAge(Integer.valueOf(tv_s.getText().toString()));
                    ref.setValue(user);
                }
            });
    
            br.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ref.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            User u = dataSnapshot.getValue(User.class);
                            if (u != null)
                                tv_r.setText(String.valueOf(u.getAge()));
                            else
                                tv_r.setText("Bad Value");
                        }
    
                        @Override
                        public void onCancelled(FirebaseError firebaseError) {
    
                        }
                    });
                }
            });
    
            ref.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    User u = dataSnapshot.getValue(User.class);
                    u.setCounter(u.getCounter() + 1);
                    user = u;
                    saveUser();
                }
    
                @Override
                public void onCancelled(FirebaseError firebaseError) {
    
                }
            });
        }
    
        public void saveUser() {
            ref.setValue(user);
        }
    }
    

    However, this change nothing, even worst. Now it seems that every value set, stay as a ghost value (hold by client/server request), and the value toggling can be seen with every values set !

    EDIT

    The following code worked out ! Having a normal ValueListener, that you stopped before saving again a value, and you enable back when save is completed ! (Ok I was thinking this may be done in the Firebase Framework).

    public class MainActivity extends AppCompatActivity {
    
        Firebase ref;
        User user;
        private ValueEventListener theListener;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ref = new Firebase("https://test.firebaseIO.com").child("user");
            ref.keepSynced(false);
    
            Button bs = (Button) findViewById(R.id.b_save);
            final EditText tv_s = (EditText) findViewById(R.id.tv_value_tosave);
    
            user = new User();
    
            bs.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!tv_s.getText().toString().equalsIgnoreCase(""))
                        user.setAge(Integer.valueOf(tv_s.getText().toString()));
                    ref.setValue(user);
                }
            });
    
    
            theListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    User u = dataSnapshot.getValue(User.class);
                    u.setCounter(u.getCounter() + 1);
                    user = u;
                    updateUI(u);
                    saveUser();
                }
    
                @Override
                public void onCancelled(FirebaseError firebaseError) {
    
                }
            };
    
            ref.addValueEventListener(theListener);
        }
    
        public void saveUser() {
            ref.removeEventListener(theListener);
            ref.setValue(user, new Firebase.CompletionListener() {
                @Override
                public void onComplete(FirebaseError firebaseError, Firebase firebase) {
                    ref.addValueEventListener(theListener);
                }
            });
        }
    
        public void updateUI(User user) {
    
            TextView tv_r = (TextView) findViewById(R.id.tv_value_toread);
            if (user != null)
                tv_r.setText(String.valueOf(user.getAge()));
            else
                tv_r.setText("Bad Value");
        }
    }
    

    EDIT

    However this do not allow to change a value on the admin page. The age value is set and then remain back to the one that is save on the mobile.

    So I imaging then the only solution is to solve at system level. DO NOT USE VALUELISTENER FOR VALUE THAT AN APP CAN SAVE AND THAT CAN BE SAVED BY THIRD PARTY APP. Please advise/correct this assumption !

提交回复
热议问题