【问题标题】:Firebase DB and Android: Lack of synchronism using a class for Firebase different from the activity/fragment classFirebase DB 和 Android:使用与活动/片段类不同的 Firebase 类缺乏同步
【发布时间】:2017-01-13 17:38:06
【问题描述】:

我正在使用 Firebase 作为数据库在 Android Studio 中开发一个应用程序,但我遇到了一个棘手的问题。我有一个从辅助类获取“pregunta”对象的片段,我在其中对数据库进行实际查询。问题是侦听器启动了一个单独的线程来等待事件,但与此同时该方法继续处理并返回一个空值。

关于如何避免这种异步或更好的实现方法的任何想法?谢谢!!

片段类:

    mPregunta = mSesionManager.getPregunta(id_pregunta_actual);
    TextView view_pregunta = (TextView)view.findViewById(R.id.titulo_pregunta);
    view_pregunta.setText(mPregunta.getTxt_pregutna());

辅助类方法:

public pregunta getPregunta(long id){
    mp.setId_pregunta(id);

    Query query = mDB_Cuestionario.child("Tabla_Preguntas").orderByChild("id").equalTo(id);
    query.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            mp.setTxt_pregutna(dataSnapshot.child("txt").getValue().toString());
            Log.e("FBHELPER", "ID LISTENER: "+mp.getId_pregunta());
            Log.e("FBHELPER", "TXT LISTENER: "+mp.getTxt_pregutna());
        }

        [-- rest of code --]
    });

    Log.e("FBHELPER", "TXT RESPUESTA: "+mp.getTxt_pregutna());
    return mp;
}

日志:

The method returns null value: 
    01-13 17:16:52.101 8994-8994/com.example.fran.cuestionario E/FBHELPER: TXT RESPUESTA: null

1 second later, the Event occurs, but I can't return the value. 
    01-13 17:16:53.497 8994-8994/com.example.fran.cuestionario E/FBHELPER: ID LISTENER: 0
    01-13 17:16:53.497 8994-8994/com.example.fran.cuestionario E/FBHELPER: TXT LISTENER: TEST VALUE

【问题讨论】:

  • 你可以public pregunta getPregunta(long id, ChildEventListener listener){ //.. query.addChildEventListener(listener); //.. } 然后更新你的片段类

标签: android android-fragments firebase firebase-realtime-database


【解决方案1】:

当您向 Firebase 注册侦听器时,该注册不会阻塞正在运行的线程。那个听众正在说:“当该数据中的某些内容可用时,请告诉我 - 我知道它不会立即发生,而是稍后发生”。

您必须围绕这些侦听器的工作方式来设计您的应用。您必须对来自侦听器的传入信息做出反应,而不是阻塞其上的任何线程。

【讨论】:

  • 我已将代码从辅助类移动到片段类,至少应用程序显示了从数据库获取的内容。但是,从用户的角度来看,它不是最佳的,因为片段正在等待(或侦听)Firebase,然后填充 TextView 而不是直接获取数据,所以会出现“闪烁”。关于如何获得更流畅的可视化的任何想法?
  • 在等待结果时显示微调器或一些过渡视图。
【解决方案2】:

我最终所做的是基于 Hhorn 关于使用 ArrayLists 的建议。因为我需要根据参数选择各种元素,所以我只是做了一个基本的搜索算法方法,它返回另一个数组,我可以将它传递给适配器以在屏幕上显示它。

加载

@Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {

                respuesta r = new respuesta(
                        Integer.valueOf(dataSnapshot.child("id_po").getValue().toString())
                        , String.valueOf(dataSnapshot.child("txt").getValue().toString())
                        );
                mSesionManager.mArrayRespuestas.add(r);

            }

搜索:

public ArrayList<respuesta> queryRespuestasFB(long id_pregunta_origen){
        ArrayList<respuesta> respuestas_seleccionadas = new ArrayList<respuesta>();

        for(respuesta r : mArrayRespuestas){
            if (r.getId_pregunta_origen()==id_pregunta_origen){
                respuestas_seleccionadas.add(r);
                //Log.e("SM", "Respuesta Query: "+ r.toString());
            }
        }

        return respuestas_seleccionadas;
    }

【讨论】:

    【解决方案3】:

    你不能那样做。 Firebase 监听器是异步的,因此它会在 Firebase 加载数据之前返回。

    我也试过了,没有办法那么容易做到。但是您可以在应用启动时预加载所有数据并将其保存在 hashmap 或 ArrayList 等中。然后您可以轻松地在 Activity 中检索列表以及所有片段。

    我就是这样做的,而且效果很好。如果您想了解更多信息,请告诉我。

    【讨论】:

    • 感谢 Hhorn 的回答,我相信这在某些情况下会起作用。但是我实际上正在测试 Firebase 非 SQL 数据库,并认为基于其他不是关键的属性来选择元素会更容易,使用 HashMaps 或数组会使这复杂化......我会看看如果我能做得很好的话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    • 2016-09-11
    • 2016-08-05
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    相关资源
    最近更新 更多