【问题标题】:How to access (modify, add elements) to an ArrayList/Collection in an Inner class in java?如何访问(修改、添加元素)到 Java 内部类中的 ArrayList/Collection?
【发布时间】:2017-02-10 18:24:09
【问题描述】:

我有这个搜索功能,可以使用 GeoFire 使用 Firebase 数据库搜索特定用户。

我想做什么:

GeoQueryEventListener()onKeyEntered 中,我想将找到的每个键添加到一个ArrayList(onKeyEntered() 之外)。

我遇到的问题:

当我在onKeyEntered() 中打印它时,它可以工作。 但是一旦我退出GeoQueryEventListener()keysGeolocated 就是空的

public ArrayList<User> search(GeoFire geoFire, int day, final boolean isBartender, double latitude, double longitude, double radius, double rate, double nightlyRate, double hourlyRate, final String speciality){

    keysGeolocated = new ArrayList<>();
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    root = database.getReference();
    DatabaseReference usersRef = root.child("Users");

    GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), radius);
    geoQuery.addGeoQueryEventListener(new MyGeoListener(keysGeolocated));

    System.out.println("KEYS GEOLOCATED" + keysGeolocated);

    final ArrayList<User> result = new ArrayList<>();

    for(String key : keysGeolocated){

        Query queryByLocation = usersRef.orderByKey().equalTo(key);
        DatabaseReference refToLocationQuery = queryByLocation.getRef();

        if(checkRefNull(refToLocationQuery) == true) {
            System.out.println("QUERY BY LOCATION NULL");
            continue;
        }

        Query queryByTypeOfUser  = refToLocationQuery.orderByChild("isBarTender").equalTo(isBartender);
        DatabaseReference refToTypeOfUserQuery = queryByTypeOfUser.getRef();

        if(checkRefNull(refToTypeOfUserQuery) == true) {
            System.out.println("QUERY BY TYPE NULL");
            continue;
        }
        Query queryByRate  = refToTypeOfUserQuery.orderByChild("rate").startAt(rate);
        DatabaseReference refToRateQuery = queryByRate.getRef();

        if(checkRefNull(refToRateQuery) == true) {
            System.out.println("QUERY BY RATE NULL");
            continue;
        }

        DatabaseReference finalRef = null;

        if(isBartender == true){

            if(nightlyRate == 0){
                Query queryByPrice  = refToRateQuery.orderByChild("nightlyRate").endAt(nightlyRate);
                finalRef = queryByPrice.getRef();
            }
            else if(hourlyRate == 0){
                Query queryByPrice  = refToRateQuery.orderByChild("hourlyRate").endAt(hourlyRate);
                finalRef = queryByPrice.getRef();
            }

            //TODO Impelement checks for available dates

        }
        else{
            finalRef = refToRateQuery;
        }

        finalRef.addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                if(dataSnapshot.getValue()!=null){

                    User userFound = dataSnapshot.getValue(User.class);

                    if(isBartender == true){
                        Bartender barTenderFound = (Bartender) userFound;
                        if(speciality != null){
                            if(barTenderFound.getSpeciality().contains(speciality)){
                                result.add(barTenderFound);
                            }
                        }
                        else{
                            result.add(barTenderFound);
                        }
                    }
                    else{
                        result.add(userFound);
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

    }

    return result;
}

public boolean checkRefNull(DatabaseReference ref){

    final boolean[] result = new boolean[1];
    result[0] = false;

        ref.addValueEventListener(new ValueEventListener() {


            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                System.out.println("TEST1");
                if(dataSnapshot.getValue()==null){
                    result[0] = true;
                    System.out.println("TESTTEST");
                }
                else{
                    System.out.println("TESTTEST TRUE" + dataSnapshot.getValue());
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
    });

    return result[0];
}

public void setBarTender(boolean barTender){

    this.barTender = barTender;
}
}

class MyGeoListener implements GeoQueryEventListener {

private ArrayList<String> keysGeolocated;

MyGeoListener(ArrayList<String> keysGeolocated){
    this.keysGeolocated = keysGeolocated;
}

@Override
public void onKeyEntered(String key, GeoLocation location) {
    keysGeolocated.add(key);
}

@Override
public void onKeyExited(String key) {

}

@Override
public void onKeyMoved(String key, GeoLocation location) {

}

@Override
public void onGeoQueryReady() {

}

@Override
public void onGeoQueryError(DatabaseError error) {

}
}

【问题讨论】:

  • 更改范围。不能是该方法的本地。
  • 您假设来自侦听器的即时结果。如果它是同步的,您的调用将打印该列表。不幸的是,这个监听器是异步的。当事件触发时,它将在列表中添加数据。过了一段时间,您才能看到打印的作品。
  • 必须是匿名类吗? :-}

标签: java android firebase inner-classes geofire


【解决方案1】:

创建一个扩展该侦听器并覆盖所有方法的类

class MyGeoListener extends GeoQueryEventListener{

    private ArrayList<String> keysGeolocated;

    MyGeoListener(ArrayList<String> keysGeolocated){
          this.keysGeolocated = keysGeolocated;
    }

    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        keysGeolocated.add(key);
        System.out.println("1111111111 : "+keysGeolocated);
        System.out.println("2222222222 : "+key);
    }

    @Override
    public void onKeyExited(String key) {

    }

    @Override
    public void onKeyMoved(String key, GeoLocation location) {

    }

    @Override
    public void onGeoQueryReady() {

    }

    @Override
    public void onGeoQueryError(DatabaseError error) {

    }
}

现在使用这个类如下:

geoQuery.addGeoQueryEventListener(new MyGeoListener(keysGeolocated));

由于侦听器是异步的并且需要时间来填充列表,因此立即下一次调用将始终不打印列表中的任何值。

尝试将打印内容放入延迟处理程序中,延迟时间为 30000 毫秒。您可能会在列表中看到条目,因为那时监听器事件应该已经触发了。

由于 arraylist 是可变的并且您传递它的引用,因此在侦听器调用时,参数中的 arraylist 也会被修改。

祝你好运,如果您仍有问题,请告诉我。

【讨论】:

  • 非常感谢您的快速回答!不幸的是,它仍然不起作用:s
  • 现在有什么问题?
  • 我已经用当前代码更新了帖子。打印keysGeolocated时,我得到:System.out:KEYS GEOLOCATED []仍然..:s
  • 老兄,监听器是异步的。它不会立即填满列表。需要花时间。您打印是一个立即调用。让监听器完成,然后您的列表中才会有条目。
  • 这是我的想法。但事实是,我在 print 语句之后迭代 ArrayList(如你所见),然后,我迭代 throw 并清空 arrayList... 有没有办法告诉函数等待侦听器结束在继续之前?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
相关资源
最近更新 更多