完成时在另一个线程中调用方法 [英] Call method in another thread on completion

查看:39
本文介绍了完成时在另一个线程中调用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在使用Firebase实时数据库.因此,我的数据更改来自另一个线程.因此,我无法控制何时更新新数据.然后我怎么知道何时调用刷新我的UI?

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

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

这是在Route类中找到的removeRoute()方法

  public void removeRoute(){//删除所有路线说明DatabaseReference mRef = FirebaseDatabase.getInstance().getReference().child(路线").child(routeId).child(路线说明");mRef.addListenerForSingleValueEvent(new ValueEventListener(){@Override公共无效onDataChange(DataSnapshot dataSnapshot){对于(DataSnapshot routeInstruc:dataSnapshot.getChildren()){routeInstruc.getValue(RouteInstructions.class).removeRouteInstructions();}DatabaseReference mRef2 = FirebaseDatabase.getInstance().getReference().child(路线").child(routeId);mRef2.removeValue();}@Override公共无效onCancelled(DatabaseError databaseError){}});} 

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

我认为我也许可以使用Looper,但如何在Route类中使用它呢?

谢谢

解决方案

您正在寻找的是回调.

回调在处理异步调用时实际上是必需的,因为调用异步任务时,基本上是在要求工作线程为您工作.
这可能需要1秒,10秒,10分钟等,并且您不确定.您可以做的是委派该工作线程,并告诉她嘿,当您完成我给您的任务时回覆".
输入回调!

您可以在此处查看有关回调的更多文档

说您已经用ValueEventListener定义了查询

  query.addListenerForSingleValueEvent(new ValueEventListener(){@Override公共无效onDataChange(DataSnapshot数据){}} 

您应该做的是具有一个回调方法,该方法将在查询侦听器返回值后立即回复(换句话说,当您执行查询时).因此,使用类似 'onResponseReceivedFromFirebase' 的方法并在回调中实现

 公共类MyActivity扩展了Activity {@Override受保护的void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);}//在此处使用所需的参数实现回调(例如,我在此处使用了String)公共无效的onResponseReceivedFromFirebase(String参数){Log.d(MyActivity.class,argument);}....query.addListenerForSingleValueEvent(new ValueEventListener(){@Override公共无效onDataChange(DataSnapshot数据){onResponseReceivedFromFirebase(响应到达!");}}...} 

@编辑根据您更新的代码,我将继续进行以下操作

  @Override公共无效onDataChange(DataSnapshot dataSnapshot){对于(DataSnapshot routeInstruc:dataSnapshot.getChildren()){routeInstruc.getValue(RouteInstructions.class).removeRouteInstructions();}DatabaseReference mRef2 = FirebaseDatabase.getInstance().getReference().child(路线").child(routeId);mRef2.removeValue();//在此处实现回调MyActivity.this.onResponseReceivedFromFirebase(我们已经收到来自dataChanged的响应");} 

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

非常导入:如果即将处理的数据的处理有效载荷非常大,则应将相同的处理传递到另一个线程(例如AsyncTask)中,以免使您的应用程序无响应. >

Currently, I am using firebase Realtime Database. Hence, my data changes come from another thread. Hence, I have no control on when the fresh data update comes over. How do I then know when to call to refresh my UI?

This is my implementation of a swipe to delete in a RecyclerView.

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

This is the removeRoute() method found in my Route class

 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) {

            }
        });
    }

As you can see, the onDataChange() is called by another thread. Which means i do not know when to call my refreshUI() method.

I think i might be able to use a Looper but how do i fit that in the Route class?

Thanks

解决方案

What you are looking for are callbacks.

Callbacks are practically mandatory when dealing with asynchronous calls, because when you call an asynchronous task, you are basically asking a worker thread to work for you.
It may take 1 second, 10 seconds, 10 minutes, etc, and you can not know for sure. What you can do is delegate that same worker thread and tell her "hey, reply back when you finish the task I gave you".
Enter the callbacks!

You can check for more documentation regarding callbacks here

Say that you have your query defined with the ValueEventListener

query.addListenerForSingleValueEvent(new ValueEventListener() {
   @Override
   public void onDataChange(DataSnapshot data) {

   }
}

What you should do is have a callback method that replies back as soon as the query listener returns a value (in other words, when your query is executed). So, have a method like 'onResponseReceivedFromFirebase' and implement it on the callback

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 Base on your updated code, I would proceed with the following

@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 : On Frank van Puffelen's remark, the onDataChange method already runs on the Main Thread, thus allowing you to change any element on the UI.

Very import : If the processing payload of the outcoming data is considerably large, you should pass that same processing into another thread (e.g. An AsyncTask) to avoid making your app non-responsive.

这篇关于完成时在另一个线程中调用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆