我正在开发一个简单的APOD应用程序,我在其中显示用户可以滚动的RecyclerView
天文图片。我启用了FirebaseDatabase.setPersistenceEnabled(true);
,因此用户可以离线使用该应用并减少连接/下载带宽。问题是如果我设置FirebaseDatabase.setPersistenceEnabled(true);
,我的应用启动时间明显更长(启用6秒vs 1.5秒禁用)。我了解用户第一次启动应用时加载时间应该更长(因为设置了持久性),但是不应该每次后续启动应用都要短得多,因为它不会查询在线Firebase服务器吗?
为了防止一次加载多行,我一个接一个地发射两个SingleValueEventListeners
。第一个加载100行并使用AsyncTask
循环通过databaseSnapshot,然后显示图像。然后我调用第二个SingleValueEventListener
并以相同的方式循环遍历它。第二个SingleValueEventListener
加载剩余数据,从101 - 7000。
以下是扩展GlobalApp
的{{1}}课程。这是我启用持久性的地方。接下来的两种方法是我加载数据的地方。
扩展应用程序类
Application
初始加载
public class GlobalApp extends Application {
@Override
public void onCreate() {
super.onCreate();
FirebaseDatabase mDatabaseReference = FirebaseDatabase.getInstance();
mDatabaseReference.setPersistenceEnabled(true);
}
}
第二次加载
private void initialLoad() {
databaseReference.child("apod").orderByChild("date").limitToLast(100).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
new LoadFirebase().execute(dataSnapshot);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
如果我使用private void secondLoad() {
final String secondKey = firebaseKeys.get(firebaseKeys.size() - 1);
databaseReference.child("apod").orderByChild("date").endAt(secondKey).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
new SecondLoadFirebase().execute(dataSnapshot);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
启动应用,我的FirebaseDatabase.setPersistenceEnabled(true);
会填充:
Logcat
接下来是一堆GC调用:
04-18 18:22:22.649 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1344 bytes, free space 752 bytes, window size 2097152 bytes
04-18 18:22:22.733 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1821 bytes, free space 1124 bytes, window size 2097152 bytes
04-18 18:22:22.798 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1580 bytes, free space 1516 bytes, window size 2097152 bytes
04-18 18:22:22.868 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1574 bytes, free space 656 bytes, window size 2097152 bytes
04-18 18:22:22.920 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1455 bytes, free space 228 bytes, window size 2097152 bytes
04-18 18:22:22.973 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1579 bytes, free space 1000 bytes, window size 2097152 bytes
04-18 18:22:23.055 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1557 bytes, free space 756 bytes, window size 2097152 bytes
04-18 18:22:23.120 2884-2915/com.foo.apod W/CursorWindow: Window is full: requested allocation 1263 bytes, free space 620 bytes, window size 2097152 bytes
似乎问题可能出在SQLite上,因为Firebase会在那里存储数据。我将Stetho添加到我的应用程序并尝试在浏览器中查看数据库(以为我在某种程度上创建了启用了持久性的重复项),但我无法访问数据库,它没有显示任何内容。
有没有人知道为什么会这样?花了很长时间才找出问题的起源。
如果您需要更多代码,请与我们联系。
由于
答案 0 :(得分:4)
不幸的是,Firebase实时数据库没有实现其脱机查询的属性索引。如果您在某个位置(在您的情况下为/ apod)进行查询,则需要扫描该位置的所有缓存数据以查找匹配结果,即使只有少量数据(100或甚至1) )符合您的查询。因此,我认为您的缓慢可能是因为扫描了您存储的7000多个条目。
作为一种解决方法,如果您可以组织您的数据,以便您可以在更精细的位置阅读(例如/ apod / 2017/04 /约30个条目来查询),这可能会大大加快速度。< / p>
答案 1 :(得分:0)
我遇到了同样的问题,从Firebase阅读了许多文档后,我了解到使用
AddSingleValueEventListener
在启用persistanceMode的情况下将无法正常工作。 AddSingleValueEventListener仅侦听本地内存,而不侦听数据库本身。在运行之前它不会更新:
AddValueEventListener or ChildEventListener
请勿使用AddSingleValueEvenetListener。只能使用:
AddValueEventListener or ChildEventListener
如果启用了持久模式