【问题标题】:update UI after two async operations两次异步操作后更新 UI
【发布时间】:2018-09-30 06:25:37
【问题描述】:

我在 android 中使用 google Firebase 数据库。我需要两个从数据库中获取两组数据——userInfo 和 assignmentInfo。然后我需要将它们组合起来并在回收站视图中显示数据。解决这个问题的最佳方法是什么?由于数据的获取是异步的,这变得很混乱。

我能想到的一种方法是,如果其他异步函数已完成,则检查两个异步函数是否成功。如果是,则获取其数据,合并并初始化适配器。这是最好的方法吗?

【问题讨论】:

  • 你在项目中使用 Rx 吗?
  • 不,基于火的数据获取是异步的
  • 你看过 ObservableInteger 吗?我确实用它解决了这种问题

标签: java android asynchronous firebase-realtime-database


【解决方案1】:

我在没有 Rx/Coroutines/其他东西的项目中使用的最简单的方法。只需创建AtomicInteger。初始化它的值等于异步操作的数量。然后在你的异步函数的每个回调中调用这个:

if(counter.decrementAndGet == 0) { your_final_action}.

如果您需要我之前提到的其他方式的帮助,请随时问我。

【讨论】:

  • 是的。因为您使用的是 Atomics。
  • 与同步方法/锁相比,原子非常轻巧且快速
【解决方案2】:

这可以使用一个简单的变量来实现,如果两个数据都可以合并并从 Firebase 成功返回,该变量将递增或保留一个标志。但是,这既不是最好的方法,也不会一直有效,因为如果两个异步线程同时尝试更新标志,它可能会失败。然后使用上面给出的实现,只有当你可以使整个操作线程安全时才会起作用。

如果您考虑自己构建一个线程安全的实现,那也不是那么困难。您可能只考虑使用 Synchronized 函数,该函数将更新您保留的标志,以检测是否从 firebase 获取了两个数据。

但是,我建议使用LocalBroadcastReceiver 完成您的实施。哪个更容易实现,这是一个 Android 解决方案。尽管可能还有其他几种很棒的方法,但我认为BroadcastReceiver 的实现将完全满足您的目的。

您可以检查this answer 以检查BroadcastReceiver 的实现。当从firebase获取数据的第一部分时,将广播发送给Activity中的BroadcastReceiver接收并设置一个标志值,例如1。然后当第二部分接收到时,你将不得不只需在从 firebase 获得响应时发送广播,即可将值再次设置为 2。然后,当找到值 2 时,这意味着两个操作都已完成,现在您可以合并两个列表。

为避免整体线程安全和故障安全编码开销,您可以考虑从 firebase 同步获取数据。在获取第一部分的数据后,启动第二部分的获取操作,以便更好地控制您的代码。

我刚刚提出了一些想法,选择任何适合你的。希望有帮助!

【讨论】:

    【解决方案3】:

    当我在用户登录到应用程序之前必须从数据库下载某些东西时,我已经解决了这种问题,我解决了这个问题。

    要使用ObservableInteger,您可以这样做

    先声明

    private ObservableInteger mObsInt;
    

    然后在您的 onCreate 中,您将有一个监听器等待 mObsInt 的值发生变化,在这些值发生变化后,您可以做任何您想做的事情

    //Listener
            mObsInt = new ObservableInteger();
            mObsInt.set(0);
    
            mObsInt.setOnIntegerChangeListener(new OnIntegerChangeListener()
            {
                @Override
                public void onIntegerChanged(int newValue)
                {
                    if (mObsInt.get()==1)
                       //Do something if the first asyncTask finishes
                    if (mObsInt.get()==2){
                       //Do something if the second asyncTask finishes, in this case i just go to another activity when both asyncTasks finish
                        Intent mainIntent = new Intent().setClass(LoginActivity.this, Principal.class);
                        startActivity(mainIntent);
                        finish();
                    }
                }
            });
    

    那么,它是如何工作的

    ObservableInteger 将寻找变量mObsInt 的变化,所以假设mObsInt 等于1 它将做某事,如果等于2 将做另一件事,所以,要解决这个问题使用 2 asynctasks 很容易,当其中一个 asynctasks 完成时 mObsInt 将等于 1 ,如果另一个 asyncTask 完成所以 mObsInt 将是 mObsInt++ ,然后你的 mObsInt 将是等于 2,侦听器将等待值,然后当值与 onCreate 方法中的 if 语句匹配时执行您想要执行的操作

    现在,只需在您的 asynctasks 中放入您的 onPostExecute() 方法这一行

    mObsInt.set(mObsInt.get()+1);
    

    所以如果第一个异步完成,mObsint == 1,如果第二个完成 mObsInt == 2,然后你在 onCreate 方法中处理你想要做的事情

    希望对你有帮助,对我有帮助

    您可以在此文档中获取更多信息:https://developer.android.com/reference/android/databinding/ObservableInt.html

    编码愉快!

    【讨论】:

      猜你喜欢
      • 2015-07-26
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 2019-11-07
      • 2011-01-22
      相关资源
      最近更新 更多