完成时调用另一个线程中的方法

时间:2016-08-09 12:28:31

标签: android firebase-realtime-database

目前,我正在使用firebase实时数据库。因此,我的数据更改来自另一个线程。因此,我无法控制新数据更新的时间。那我怎么知道何时打电话来刷新我的用户界面呢?

这是我在RecyclerView中删除滑动的实现。

    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        int pos = viewHolder.getAdapterPosition();
        mListRoute.get(pos).removeRoute();
        refreshUI();
    }

这是我的Route类

中的removeRoute()方法
 public void removeRoute() {
        //Delete all the Route Instructions
        DatabaseReference mRef = FirebaseDatabase.getInstance().getReference()
                .child("Routes")
                .child(routeId)
                .child("Route Instructions");

        mRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot routeInstruc : dataSnapshot.getChildren()) {
                    routeInstruc.getValue(RouteInstructions.class)
                            .removeRouteInstructions();
                }

                DatabaseReference mRef2 = FirebaseDatabase.getInstance().getReference()
                        .child("Routes")
                        .child(routeId);
                mRef2.removeValue();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

如您所见, onDataChange() 由另一个线程调用。这意味着我不知道何时调用我的 refreshUI() 方法。

我想我可以使用Looper但是我如何在Route类中使用它?

谢谢

2 个答案:

答案 0 :(得分:1)

您正在寻找的是回调

处理异步调用时,

回调几乎是强制性的,因为当您调用异步任务时,基本上是要求工作线程为您工作。
它可能需要1秒,10秒,10分钟等,你无法确定。你可以做的是委托同一个工人线程并告诉她“嘿,当你完成我给你的任务时回复”。
输入回调!

You can check for more documentation regarding callbacks here

假设您使用ValueEventListener

定义了查询
query.addListenerForSingleValueEvent(new ValueEventListener() {
   @Override
   public void onDataChange(DataSnapshot data) {

   }
}

你应该做的是有一个回调方法,一旦查询监听器返回一个值(换句话说,执行你的查询时)就会回复。 那么,有一个类似 'onResponseReceivedFromFirebase' 的方法并在回调中实现它

public class MyActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    // Implement your callback here with the parameters you want (for instance, I used a String there)
    public void onResponseReceivedFromFirebase(String argument){
        Log.d(MyActivity.class,argument);
    }

    ....

    query.addListenerForSingleValueEvent(new ValueEventListener() {
       @Override
       public void onDataChange(DataSnapshot data) {
            onResponseReceivedFromFirebase("the response arrived!");
       }
    }

    ...

}

@Edit 根据您更新的代码,我将继续以下

@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot routeInstruc : dataSnapshot.getChildren()) {
         routeInstruc.getValue(RouteInstructions.class)
        .removeRouteInstructions();
    }
    DatabaseReference mRef2 = FirebaseDatabase.getInstance().getReference()
                    .child("Routes")
                    .child(routeId);
            mRef2.removeValue();
   // Implement the callback here 
   MyActivity.this.onResponseReceivedFromFirebase("We have received a response from   dataChanged");
}

@Edit 2:在Frank van Puffelen的评论中,onDataChange方法已在主线程上运行,因此允许您更改UI上的任何元素。

非常重要:如果输出数据的处理负载相当大,您应该将相同的处理传递到另一个线程(例如AsyncTask),以避免使您的应用无响应。

答案 1 :(得分:1)

当Firebase客户端在单独的线程上处理所有网络和磁盘IO时,它会调用主线程上代码的回调。因此,您可以直接从onDataChange()更新UI,而无需自己担心该主题。

事实上,Firebase文档中的所有示例都会通过其onDataChange()(或onChild...())回调更新用户界面。一个example from the database quickstart

public void onDataChange(DataSnapshot dataSnapshot) {
    // Get Post object and use the values to update the UI
    Post post = dataSnapshot.getValue(Post.class);
    mAuthorView.setText(post.author);
    mTitleView.setText(post.title);
    mBodyView.setText(post.body);
}