代码之家  ›  专栏  ›  技术社区  ›  Christopher Mills

如何基于Firebase事务结果影响android活动中的视图

  •  0
  • Christopher Mills  · 技术社区  · 6 年前

    我的活动中有以下Firebase事务:

    private void onRoomAccept(DatabaseReference thisRoomRef) {
            thisRoomRef.runTransaction(new Transaction.Handler() {
                @Override
                public Transaction.Result doTransaction(MutableData mutableData) {
                    Room r = mutableData.getValue(Room.class);
    
                    if (r != null && r.State.equals("Open")) {
    
                        r.Tutor = UserID;
                        r.State = "Live";
    
                        // Set value and report transaction success
                        mutableData.setValue(r);
                        return Transaction.success(mutableData);
    
                    } else if (r == null || r.State.equals("Live")){
                        Intent intent3 = new Intent(TutorChatActivity.this, TutorActivity.class);
                        startActivity(intent3);
                    }
                return Transaction.success(mutableData);
            }
    
            @Override
            public void onComplete(DatabaseError databaseError, boolean b,
                                   DataSnapshot dataSnapshot) {
                // Transaction completed
                Log.d(TAG, "postTransaction:onComplete:" + databaseError);
            }
        });
    }
    

    这个很好用。然而,我想在其上构建一些视图更改。例如,如果事务成功(意味着在数据库中设置了更新的“r”值),我想更改按钮的可见性。

    以下内容被添加到事务中,以导致下面给出的错误:

    Positive.setVisibility(View.INVISIBLE);
    Negative.setVisibility(View.INVISIBLE);
    

    同样,对于不成功的结果,我想弹出一个对话框,说明出现了故障,然后再将用户返回到TutorActivity(本例中为TutorActivity)。

    我尝试了这一点,但出现了一个错误,指出只有活动可以更改其自己的视图(这对我来说是有意义的):

    postTransaction:onComplete:DatabaseError: User code called from the Firebase Database runloop threw an exception:
                                                                               android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                                   at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7901)
                                                                                   at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1360)
                                                                                   at android.view.ViewGroup.invalidateChild(ViewGroup.java:5448)
                                                                                   at android.view.View.invalidateInternal(View.java:14829)
                                                                                   at android.view.View.invalidate(View.java:14793)
                                                                                   at android.view.View.setFlags(View.java:12684)
                                                                                   at android.view.View.setVisibility(View.java:8673)
                                                                                   at website.picl.picl.Activities.TutorChatActivity$7.doTransaction(TutorChatActivity.java:365)
                                                                                   at com.google.android.gms.internal.zzdsf.zza(Unknown Source)
                                                                                   at com.google.firebase.database.zzf.run(Unknown Source)
                                                                                   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
                                                                                   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
                                                                                   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                                   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    

    因此,回到我的问题中,我将如何使用事务的结果来改变我的观点(不必使用单独的值事件侦听器,我只考虑它作为最后一个选项,因为它比较慢,导致更多的服务器调用)。

    2 回复  |  直到 6 年前
        1
  •  0
  •   Alex Mamo    6 年前

    Firebase数据库客户端在后台线程中运行所有网络操作。这意味着你不能在后台线程中创建/修改视图。您只能在创建这些视图的线程中修改UI。然而,允许您进行这些更改的线程是主线程,因此您需要从事务中取出这些代码行。

    你的解决方案是,添加 ValueEventListener (交易之外)在该特定价值上,一旦交易成功 onDataChange() 方法,在该方法中,您可以创建/修改任意多个视图。

    注: 整个视图树是单线程的。因此,在任何视图上调用任何方法时,必须始终处于UI线程上。如果您正在其他线程上工作,并且希望从该线程更新视图的状态,那么应该使用 Handler .

    你可以找到更多 here .

        2
  •  0
  •   Christopher Mills    6 年前

    我找到了一种与活动中的视图进行交互的方法,而无需依赖单独的听众:

    我在我的交易代码中的IF语句中插入以下内容,如我的原始问题所示:

    getIntent().removeExtra("ORIGIN");
    getIntent().putExtra("ORIGIN", "TransactionSuccess");
    startActivity(getIntent());
    

    然后,在我的活动的onCreate中,我在IF语句中处理ORIGIN等于“TransactionSuccess”的情况下所需的视图更改:

    //This is in my onCreate:
    
    Intent intent = getIntent();
    String origin = intent.getStringExtra("ORIGIN");
    
    if (origin.equals("TransactionSuccess"){
    
    this.overridePendingTransition(0, 0);
    
    //Set my view changes here.
    
    }
    

    此外,为了避免活动刷新时出现滑入动画,我在同一个onCreate IF语句中包含以下内容(如图所示):

    this.overridePendingTransition(0, 0);
    

    与依赖数据库侦听器相比,这种方法允许更快地更改视图。

    当活动重新启动时,现有视图仍会有短暂的闪现,但我将在侦听器相对较长的等待时间内完成。