Android 强制Firebase使用缓存数据

Android 强制Firebase使用缓存数据,android,firebase,firebase-realtime-database,Android,Firebase,Firebase Realtime Database,我想强制Firebase提供缓存数据,而不是从服务器获取最新数据。这可能吗 其想法是启用持久性,在特定位置调用keepSynced(true),添加一个侦听器以在数据可用时收到通知,然后调用keepSynced(false),以确保将来的侦听器获得缓存的数据 然而,在测试应用程序中,这似乎不起作用。调用keepSynced(false)不会阻止侦听器从服务器获取最新信息。(代码如下) 使用暂时不变的Firebase数据集的正确方法是什么 public class MainActivity ext

我想强制Firebase提供缓存数据,而不是从服务器获取最新数据。这可能吗

其想法是启用持久性,在特定位置调用
keepSynced(true)
,添加一个侦听器以在数据可用时收到通知,然后调用
keepSynced(false)
,以确保将来的侦听器获得缓存的数据

然而,在测试应用程序中,这似乎不起作用。调用
keepSynced(false)
不会阻止侦听器从服务器获取最新信息。(代码如下)

使用暂时不变的Firebase数据集的正确方法是什么

public class MainActivity extends AppCompatActivity {
  private static String TAG = "tag";
  Button keepSyncedTrue;
  Button keepSyncedFalse;
  Button getData;
  TextView data;
  private DatabaseReference myRef;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FirebaseDatabase.getInstance().setPersistenceEnabled(true);
    myRef = getDatabaseReference();
    setContentView(R.layout.activity_main);
    keepSyncedTrue = (Button)findViewById(R.id.keepSyncTrue);
    keepSyncedFalse = (Button)findViewById(R.id.keepSyncFalse);
    getData = (Button)findViewById(R.id.getData);
    data = (TextView)findViewById(R.id.data);

    keepSyncedTrue.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {
        myRef.keepSynced(true);
      }
    });

    keepSyncedFalse.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {
        myRef.keepSynced(false);
      }
    });

    getData.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {
        // Read from the database
        myRef.addListenerForSingleValueEvent(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
            // This method is called once with the initial value and again
            // whenever data at this location is updated.
            String value = dataSnapshot.getValue(String.class);
            Log.d(TAG, "Value is: " + value);
            data.setText(value);
          }

          @Override
          public void onCancelled(DatabaseError error) {
            // Failed to read value
            Log.w(TAG, "Failed to read value.", error.toException());
          }
        });
      }
    });

  }

  private DatabaseReference getDatabaseReference() {
    return FirebaseDatabase.getInstance().getReference("message");
  }
}


这取决于你的最终目标

如果要避免任何类型的同步,可以使用

DatabaseReference.goOffine();
如您所见:

手动断开Firebase数据库客户端与服务器的连接,并禁用自动重新连接

注意:调用此方法将影响所有Firebase数据库连接

否则:

FirebaseDatabase.goOffline();
如上所述:

关闭与Firebase数据库后端的连接,直到调用
goOnline()

如果希望保持同步并使用本地缓存数据,则可以使用

FirebaseDatabase.getInstance().setPersistenceEnabled(true);
如文件所述:

通过启用持久性,Firebase实时数据库客户端在联机时将同步的任何数据都会持久化到磁盘,并且即使在用户或操作系统重新启动应用程序时,也可以脱机使用。这意味着您的应用程序可以使用缓存中存储的本地数据在线工作。侦听器回调将继续触发本地更新

在这种情况下,应用程序使用缓存数据,但客户端继续与服务器数据同步。

在这种情况下,要保持特定位置的同步,请使用:

yourRef.keepSynced(true);

通过在应用程序中启用,可以使用Firebase脱机功能。这是如何做到的:

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (!FirebaseApp.getApps(this).isEmpty()) {
            FirebaseDatabase.getInstance().setPersistenceEnabled(true);
        }
    }
}
启用磁盘持久性后,Firebase listener将首先查找
DataSnapshot
中给出的缓存数据。所以,为了防止它从服务器获取数据,您应该在每次需要读取数据时使用Firebase
addListenerForSingleValueEvent
,因为它只读取一次,然后删除自身,这意味着它将从缓存数据中读取


我认为在这种情况下不需要使用
keepSynced(布尔值)

为什么要专门获取缓存数据?Firebase将根据internet的可用性为您同步所有内容。请注意,Firebase实时数据库并不真正希望您考虑是否缓存数据。它希望您假设,如果您正在积极地收听数据,它正在尽最大努力保持数据同步。它可以缓存(但不一定)这一事实是API中隐藏的一个实现细节。因此,您尝试提出的任何解决方案充其量都是“黑客式的”。@Basanth我正在使用firebase填充应用程序的内容/结构。我试图避免这样的情况:当firebase更新发生时,用户正在积极使用应用程序,而用户正在查看的部分突然不存在。@DougStevenson这是有道理的,但我希望有一种方法。我认为唯一的“非黑客”解决方案是改变获取应用程序内容/结构的方式。如果你能分享这个结构以及你打算如何使用它,我们可以提出一些解决方案。谢谢你的建议。不幸的是,我发现虽然第一个结果来自缓存,但后续请求的结果是来自firebase的最新结果。我想这已经解释过了,Frank说“Firebase客户端将(像以前的情况一样)立即调用onDataChange()从本地磁盘缓存获取值,而不会调用onDataChange()任何时候,即使服务器上的值不同。请注意,更新的数据仍将被请求并在后续请求中返回。“如果您确实想确保它来自缓存数据,那么您可能需要自己努力保存数据。如果需要,您可以使用
gson
,方法是将Firebase中的json字符串保存在
SharedReferences
中,然后使用
gson
转换为Java对象来检索它。很抱歉,我找不到一种只使用Firebase API的方法。这很有意义。谢谢。如果可以应用到特定路径,那么脱机将是完美的;不仅仅是整个数据库。我启用了持久性(将更新post),但不幸的是,我发现,虽然第一个结果来自缓存,但后续请求的结果是来自firebase的最新结果。我想这已经解释过了,Frank说“Firebase客户端将(像以前的情况一样)立即调用onDataChange()从本地磁盘缓存获取值……请注意,更新的数据仍将被请求,并在后续请求中返回。”是否有其他步骤确保它始终从缓存返回数据?但是,Docs还表示,“在Android上,Firebase会自动管理连接状态,以减少带宽和电池使用。当客户端没有活动侦听器、没有挂起的写入或onDisconnect操作,并且没有通过goOffline方法显式断开连接时,Firebase会在60秒不活动后关闭连接。”
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (!FirebaseApp.getApps(this).isEmpty()) {
            FirebaseDatabase.getInstance().setPersistenceEnabled(true);
        }
    }
}