Firebase同步如何与共享数据一起工作? [英] How does Firebase sync work, with shared data?

查看:188
本文介绍了Firebase同步如何与共享数据一起工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Firebase处理我的Android应用程序的Auth主题。
我还在Firebase上保存了用户个人资料,其中包含用户ID和用户可以在Android应用中更新的其他选项。



在启动时,应用程序检查auth和auth。它会重新加载用户个人资料(在Firebase上),然后更新我在应用上的userInstance。



Firebase在应用级别设置为脱机。
userInstance POJO与日志中的Firebase同步,并停止在unlog处同步。



我有一个特殊的参数,在我的用户配置文件中可以更改(作为管理员)。每次我在Firebase控制台上进行更新时,都会在应用程序重新启动时替换为之前的值。



这是怎么发生的?

BTW:
1 /基于哪种机制是合并的数据,如果多个客户端有不同的本地值? / p>

这里是简单的代码,我试图重现错误。 :

MyApplication.java

  public class MyApplication extends Application {
@Override
public void onCreate(){
super.onCreate();
Firebase.setAndroidContext(this);
Firebase.getDefaultConfig()。setLogLevel(Logger.Level.DEBUG);
Firebase.getDefaultConfig()。setPersistenceEnabled(true);





$ b

MainActivity

  public class MainActivity extends AppCompatActivity {

Firebase ref;
用户用户;

@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ref = new Firebase(https://millezim-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.addListenerForSingleValueEvent(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){
$ b}
});
}
});

ref.addValueEventListener(new ValueEventListener(){
@Override $ b $ 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);




$ b $ p $如果你只是改变应用程序中的一个值,柜台公司,直到应用程序停止:这是正常的。但是,什么是链是从旧到新,然后是循环而不停止的年龄。



我觉得在我的应用程序的行为,没有循环,因为我没有一个计数器,但我不能更改管理客户端中的参数,我总是回到以前的值存储在手机。

我只是身份验证,然后我更新我的UserInstance与AuthData +从Firebase的用户提取(可能是缓存的数据),然后我保存更新用户在Firebase下(因为我可能有新的AuthData,通常我会从Firebase获得最新的用户)

在这个简单的例子中,我看到如果我读在开始的值,它获取缓存在应用程序中的数据。我怎么能强制在线数据?

解决方案

这个问题来自于你使用磁盘持久性,值事件监听器。当你这样做时:

pre $ ref $ addFileStateValueEvent(new ValueEventListener(){...

如果Firebase在本地缓存中存在该位置的值,它会立即触发该值。

解决这个问题的最好方法是不使用单值侦听器,而是使用常规事件侦听器。你将得到两个事件:一个用于缓存版本,另一个用于从服务器返回的版本(如果不同)。

唯一的选择是不使用Firebase的磁盘持久性,如果没有这种情况,重新启动时就不会有数据的本地缓存。



有几个关于这个的讨论Firebase邮件列表中的组合。以下是一个: https://groups.google.com/论坛/#!味精/ F irebase-talk / ptTtEyBDKls / XbNKD_K8CQAJ


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 app.

At startup, the app check the auth, and auth. It reload the user profile (on Firebase) to then update my userInstance on the app.

Firebase is set as offline capable at app level. The userInstance POJO is sync with Firebase at log and stop to be sync at unlog.

I have a special parameter, in my user profile that I can change (as an admin).

Every-time I update it on the Firebase console, it is replaced by the previous value when the app start again.

How can this happen ?

BTW : 1/ Based on which mechanism are the data merged, if multiple client have different local values ?

Here is simpler code, where I tried to reproduce the error. :

MyApplication.java

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Firebase.setAndroidContext(this);
        Firebase.getDefaultConfig().setLogLevel(Logger.Level.DEBUG);
        Firebase.getDefaultConfig().setPersistenceEnabled(true);


    }
}

MainActivity

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://millezim-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.addListenerForSingleValueEvent(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);
    }
}

If you just change a value in the app, then the counter inc until the app stop : this is normal. But what is strand is the age pass from old to new then to old cyclically without stopping.

And I feel that behavior in my app, without the cyclic, as I do not have a counter, but I cannot change a parameter in the admin client, I always get back the previous value stored in the mobile.

I just Auth, then I update my UserInstance with AuthData + the User fetch from Firebase (probably the cached data), and then I save back the updated User under Firebase (As I may got new AuthData, and I normally get the latest User from Firebase)

2/ In this simple example, I saw that if I read the value at start, it fetch the data cached in the app. How can I force having online data ?

解决方案

The problem comes from the fact that you're using disk persistence with a single-value event listener. When you do:

ref.addListenerForSingleValueEvent(new ValueEventListener() {...

You're asking for a single value of that location (the user in your case). If Firebase has a value for that location in its local cache, it will fire for that value straight away.

The best way to solve this is to not use a single-value listener, but instead use a regular event listener. That way you will get two events: one for the cached version and one for the version that comes back from the server (if it is different).

The only alternative is to not use Firebase's disk persistence. Without that, there won't be a local cache for the data to be read from upon a restart.

There were a few discussions about this combination on the Firebase mailing list. Here's one: https://groups.google.com/forum/#!msg/firebase-talk/ptTtEyBDKls/XbNKD_K8CQAJ

这篇关于Firebase同步如何与共享数据一起工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆