【问题标题】:Reading Firebase data, onDataChange is never called读取 Firebase 数据,永远不会调用 onDataChange
【发布时间】:2017-06-25 23:18:08
【问题描述】:

我是新来的,目前我正在做的应用程序正在后台运行并检查手机中的进程,如果"com.igg.castleclash" 在进程列表中,它会将 Castleclash 值设置为 true 并在 Firebase 中保存数据。一切正常,但我无法使用 addValueEventListener 从 Firebase 读取数据。

public class SensorService extends Service {
    boolean castleclash = false;
    DatabaseReference databaaseUsers;


    public SensorService(Context applicationContext) {
        super();
    }

    public SensorService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);

        startTimer();

            databaaseUsers.child("user1").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                UsersData user = dataSnapshot.getValue(UsersData.class);
                Log.i("user name", user.getName());
            }

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

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
            Intent broadcastIntent = new
                    Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
            sendBroadcast(broadcastIntent);


    }
    public void startTimer() {
        synchronized (this) {
            while (true) {

                try {
                    wait(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                databaaseUsers = FirebaseDatabase.getInstance().getReference();
                ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
                final List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();

                for (ActivityManager.RunningAppProcessInfo process : runningProcesses) {
                    if (process.processName.equals("com.igg.castleclash")) {
                        castleclash = true;
                        break;
                    } else {
                        castleclash = false;

                    }
                }

                UsersData user1 = new UsersData(castleclash, "name");
                databaaseUsers.child("user1").setValue(user1);

            }

        }

    }



    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

任何想法为什么这不起作用?

【问题讨论】:

    标签: android firebase firebase-realtime-database


    【解决方案1】:

    存在多个问题。最重要的是,此处理不会如您所想的“在后台”发生。它在主线程上运行。这是documentation 中描述的对服务的常见误解:

    什么是服务?

    关于 Service 类的大部分困惑实际上都围绕着什么 它是不是

    • 服务不是一个单独的进程。 Service 对象本身并不意味着它在自己的进程中运行;除非另有 指定,它与它所属的应用程序在同一进程中运行 的。
    • 服务不是线程。它本身并不是一种脱离主线程工作的方法(以避免应用程序无响应错误)。

    IntentService 是一个方便的服务子类,用于在主线程之外完成工作。

    startTimer() 中的 while(true) 循环无限运行。在onStartCommend() 中对addValueEventListener() 的调用永远不会执行,因为startTimer() 永远不会返回。

    数据库更改侦听器在主线程上运行。由于主线程被wait() 的调用阻塞,onDataChange() 回调将无法运行(如果成功添加了监听器)。

    另外,要查看您在startTimer() 中对数据库的写入是否失败,请添加CompletionListener。最常见的失败原因是不正确的安全规则导致权限被拒绝。

    UsersData user1 = new UsersData(castleclash, "name");
    databaaseUsers.child("user1").setValue(user1, new DatabaseReference.CompletionListener() {
        @Override
        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
            if (databaseError == null) {
                Log.d(TAG, "onComplete: success");
            } else {
                Log.e(TAG, "onComplete: failed", databaseError.toException());
            }
        }
    });
    

    【讨论】:

    • 这对我有什么帮助?如果我可以将数据保存到 Firebase,我应该也可以读取数据,你不觉得吗?正如我所说,一切正常,但读取数据是个问题。
    • 您在发布可编译代码方面做得很好。但这不是minimal reproducible example,至少可以证明您报告的问题。当我运行您的代码时,它不能“完美运行”。它崩溃是因为它阻塞了主线程。
    • while (true) 解决了所有问题,我将 while (true) 循环放在 new Thread(new Runnable(){ public void run() { // TODO Auto-generated method stub while(true) { Thread.sleep(60000) //REST OF CODE HERE// } } }).start(); 中,现在一切正常。感谢您的帮助。
    【解决方案2】:

    您看过 David East 的这段视频吗? https://youtu.be/lpFDFK44pX8 我遵循他的方法,这很有帮助。

    第一行,你应该这样写,

    DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference

    然后,您需要在控制台中为每个数据库声明另一个 DatabaseReference。

    DatabaseReference moooww = dbRef.child("nameOfYourDbValue");

    视频中显示的其余部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-15
      • 2014-11-01
      相关资源
      最近更新 更多