Firebase 同步如何与共享数据一起工作?
我使用 Firebase 来处理我的 Android 应用的 Auth 主题.我还在 Firebase 上保存了一个用户配置文件,其中包含用户 ID 和用户可以在 Android 应用中更新的额外选项.
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.
在启动时,应用程序会检查身份验证和身份验证.它重新加载用户配置文件(在 Firebase 上),然后在应用程序上更新我的 userInstance.
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 在应用级别设置为可离线使用.userInstance POJO 在 log 时与 Firebase 同步,在 unlog 时停止同步.
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).
每次我在 Firebase 控制台上更新它时,它都会在应用重新启动时替换为之前的值.
Every-time I update it on the Firebase console, it is replaced by the previous value when the app start again.
怎么会这样?
顺便说一句:1/如果多个客户端有不同的本地值,数据是基于哪种机制合并的?
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.
我只是 Auth,然后我使用 AuthData + 从 Firebase 获取的用户(可能是缓存的数据)更新我的 UserInstance,然后我将更新后的用户保存在 Firebase 下(因为我可能得到新的 AuthData,我通常会得到Firebase 的最新用户)
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/在这个简单的示例中,我看到如果我在启动时读取值,它会获取应用程序中缓存的数据.如何强制拥有在线数据?
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() {...
您要求该位置的单个值(在您的情况下为用户).如果 Firebase 在其本地缓存中有该位置的值,它将立即为该值触发.
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).
唯一的选择是不使用 Firebase 的磁盘持久性.否则,将不会有本地缓存供重新启动时读取的数据.
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.
在 Firebase 邮件列表中有一些关于这种组合的讨论.这是一个:https://groups.google.com/forum/#!msg/firebase-talk/ptTtEyBDKls/XbNKD_K8CQAJ
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
相关文章