Android Firebase - 启动时间慢.setPersistenceEnabled(true) [英] Android Firebase - Slow startup time when .setPersistenceEnabled(true)

查看:245
本文介绍了Android Firebase - 启动时间慢.setPersistenceEnabled(true)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个简单的APOD应用程序,在其中显示 RecyclerView 天文图片,用户可以滚动浏览。我启用了 FirebaseDatabase.setPersistenceEnabled(true); ,以便用户可以脱机使用该应用程序,并减少连接/下载带宽。问题是如果我设置 FirebaseDatabase.setPersistenceEnabled(true); ,我的应用程序启动时间明显更长(启用6秒,禁用1.5秒)。我知道用户第一次启动应用程序时,加载时间应该更长(因为持久性已设置),但是不应该每次后续启动应用程序都会显着缩短,因为它不查询在线Firebase服务器?



为了避免一次加载多行,我一个接一个地激发两个 SingleValueEventListeners 。第一个加载100行,并使用 AsyncTask 循环访问databaseSnapshot,然后显示图像。然后我调用第二个 SingleValueEventListener 并以相同的方式循环。第二个 SingleValueEventListener 加载了剩余的数据,从101 - 7000.

以下是我的 GlobalApp 类,扩展应用程序。这是我启用持久性的地方。接下来的两个方法是我加载数据的地方。
$ b $ p 扩展应用程序类

 public class GlobalApp extends Application {
$ b $ @Override
public void onCreate(){
super.onCreate();

FirebaseDatabase mDatabaseReference = FirebaseDatabase.getInstance();

mDatabaseReference.setPersistenceEnabled(true);




$ b

初始加载 ()

  private void initialLoad(){

databaseReference.child(apod)。orderByChild (date)。limitToLast(100).addListenerForSingleValueEvent(new ValueEventListener(){
@Override $ b $ public void onDataChange(DataSnapshot dataSnapshot){
$ b $ new LoadFirebase()。execute (dataSnapshot);

}

@Override
public void onCancelled(DatabaseError databaseError){


}) ;

$ b

第二次加载

  private void secondLoad(){

final字符串secondKey = firebaseKeys.get(firebaseKeys.size() - 1 );
$ b $ databaseReference.child(apod)。orderByChild(date)。endAt(secondKey).addListenerForSingleValueEvent(new ValueEventListener(){
@Override $ b $ public void onDataChange DataSnapshot dataSnapshot){

SecondLoadFirebase()。execute(dataSnapshot);


$ b @Override $ b $ public void onCancelled(DatabaseError databaseError){

}
});




如果我用 FirebaseDatabase.setPersistenceEnabled(true); ,my Logcat 填充:

  04-18 18:22:22.649 2884-2915 / com.foo.apod W / CursorWindow:窗口已满:请求的分配1344字节,可用空间752字节,窗口大小2097152字节
04-18 18:22:22.733 2884-2915 / com.foo.apod W / CursorWindow:窗口已满:请求分配1821字节,空闲空间1124字节,窗口大小2097152字节
04-18 18:22: 22.798 2884-2915 / com.foo.apod W / CursorWindow:窗口已满:请求分配1580字节,空闲空间1516字节,窗口大小2097152字节
04-18 18:22:22.868 2884-2915 / com。 foo.apod W / CursorWindow:窗口已满:请求分配1574字节,可用空间656字节,窗口大小2097152字节
04-18 18:22:22.920 2884-2915 / com.foo.apod W / CursorWindow:窗口已满:请求分配1455字节,空闲空间228字节,窗口大小2097152字节
04-1 8 18:22:22.973 2884-2915 / com.foo.apod W / CursorWindow:窗口已满:请求分配1579字节,空闲空间1000字节,窗口大小2097152字节
04-18 18:22:23.055 2884 -2915 / com.foo.apod W / CursorWindow:窗口已满:请求分配1557字节,可用空间756字节,窗口大小2097152字节
04-18 18:22:23.120 2884-2915 / com.foo。 apod W / CursorWindow:窗口已满:请求分配1263字节,空闲空间620字节,窗口大小2097152字节



<接下来是一堆GC调用:

  04-18 18:22:26.290 2884-2891 / com.foo。 apod I / art:后台部分并发标记扫描GC释放171401(23MB)AllocSpace对象,0(0B)LOS对象,15%免费,85MB / 101MB,暂停2.120ms共151.451ms 
04-18 18:22 :29.153 2884-2891 / com.foo.apod I / art:背景部分并发标记扫描GC释放552106(22MB)AllocSpace对象,4(1096KB)LOS对象,15%免费,84MB / 100MB,暂停868us总计158.171ms
04-18 18:22:29 .647 2884-2891 / com.foo.apod I / art:背景粘性并发标记扫描GC释放211953(18MB)AllocSpace对象,0(0B)LOS对象,14%免费,85MB / 100MB,暂停2.590ms总计114.968ms
04-18 18:22:30.122 2884-2891 / com.foo.apod I / art:背景粘性并发标记扫描GC释放482294(17MB)AllocSpace对象,43(3MB)LOS对象,3% 96MB / 100MB,暂停1.440ms 100.242ms
04-18 18:22:31.091 2884-2906 / com.foo.apod V / FA:不活跃,断开服务

由于Firebase将数据存储在那里,因此似乎可能会出现SQLite问题。我将 Stetho 添加到我的应用程序,并试图在浏览器中查看数据库(以为我在某种程度上创建重复启用持久性),但我无法访问数据库,它什么也没有显示。

有人知道为什么会发生这种情况吗?花了很长时间才知道问题的起源在哪里。



请让我知道你是否需要更多的代码。

感谢

解决方案

不幸的是,Firebase实时数据库没有实现属性索引其离线查询。如果您在某个位置执行查询(在您的情况下为/ apod),则需要扫描该位置的所有缓存数据,以便查找匹配的结果,即使只有少量(100或甚至1 )匹配您的查询。所以我认为你的缓慢可能是由于扫描了你存储的7000多个条目。

作为一个解决方法,如果你能组织你的数据,以便你可以阅读更详细的位置(例如/ apod / 2017/04 / with〜30 entries to query over),这可能会大大加快速度。

I'm working on a simple APOD app where I display a RecyclerView of astronomy pictures that the user can scroll through. I enabled FirebaseDatabase.setPersistenceEnabled(true); so users can use the app offline and to reduce connections/download bandwidth. The problem is if I set FirebaseDatabase.setPersistenceEnabled(true);, my app startup time is significantly longer (6 seconds enabled vs 1.5 seconds disabled). I understand the first time a user launches the app the load time should be longer (because persistence is set up), but shouldn't every subsequent launch of the app be significantly shorter since it is not querying the online Firebase server?

To keep from loading many rows at once, I fire two SingleValueEventListeners, one after another. The first one loads 100 rows and loops through the databaseSnapshot using an AsyncTask, then displays the images. I then call the second SingleValueEventListener and loop through it the same way. The second SingleValueEventListener loads the remaining data, from 101 - 7000.

Below is my GlobalApp class that extends Application. This is where I enable persistence. The next 2 methods are where I load the data.

Extending Application Class

public class GlobalApp extends Application {

@Override
public void onCreate() {
    super.onCreate();

    FirebaseDatabase mDatabaseReference = FirebaseDatabase.getInstance();

    mDatabaseReference.setPersistenceEnabled(true);

    }
}

Initial Load

 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) {

        }
    });

}

Second Load

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) {

        }
    });

}

If I launch the app with FirebaseDatabase.setPersistenceEnabled(true);, my Logcat fills with:

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

Followed by a bunch of GC calls:

04-18 18:22:26.290 2884-2891/com.foo.apod I/art: Background partial concurrent mark sweep GC freed 171401(23MB) AllocSpace objects, 0(0B) LOS objects, 15% free, 85MB/101MB, paused 2.120ms total 151.451ms
04-18 18:22:29.153 2884-2891/com.foo.apod I/art: Background partial concurrent mark sweep GC freed 552106(22MB) AllocSpace objects, 4(1096KB) LOS objects, 15% free, 84MB/100MB, paused 868us total 158.171ms
04-18 18:22:29.647 2884-2891/com.foo.apod I/art: Background sticky concurrent mark sweep GC freed 211953(18MB) AllocSpace objects, 0(0B) LOS objects, 14% free, 85MB/100MB, paused 2.590ms total 114.968ms
04-18 18:22:30.122 2884-2891/com.foo.apod I/art: Background sticky concurrent mark sweep GC freed 482294(17MB) AllocSpace objects, 43(3MB) LOS objects, 3% free, 96MB/100MB, paused 1.440ms total 100.242ms
04-18 18:22:31.091 2884-2906/com.foo.apod V/FA: Inactivity, disconnecting from the service

It seems the problem might be with SQLite since Firebase stores the data there. I added Stetho to my app and tried to view the database in the browser (thinking I was somehow creating duplicates with persistence enabled), but I could not access the database, it showed nothing.

Does anyone have a clue why this is happening? It took forever to find out where the issue was originating.

Please let me know if you need anymore code.

Thanks

解决方案

Unfortunately, Firebase Realtime Database does not implement property indexing of its offline queries. If you do a query at a location (/apod in your case), it will need to scan all of the cached data at that location in order to find the matching results, even if there are only a small number (100 or even 1) that match your query. So I think your slowness is likely due to scanning the 7000+ entries you have stored.

As a workaround, if you could organize your data such that you could read at a more granular location (e.g. /apod/2017/04/ with ~30 entries to query over), that would likely speed things up considerably.

这篇关于Android Firebase - 启动时间慢.setPersistenceEnabled(true)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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