如何按自定义属性(而非数据库值)

时间:2016-08-30 03:42:55

标签: listview firebase firebase-realtime-database firebaseui

是否可以通过本地数据模型的属性(在本例中为Person.class)而不是数据库中包含的值来实现FirebaseUI ListView顺序...实时不少?

问题:我正在将基于位置的应用程序(类似于共享应用程序)从PHP / mysql转换为firebase。 (顺便说一下,我对Firebase非常兴奋......而且我已经看到很多优点)。

出于我们的目的,该应用程序只显示一个代表附近的列表视图和按距离排序的可用服务提供商。这是通过向服务器发送包括客户的纬度和经度作为POST参数的PHP请求来完成的。然后,服务器将发回JSON服务提供者列表。服务器将根据服务提供商与客户的当前距离来对结果进行排序。此外...根本不返回不可用的服务提供商。所有这一切的问题在于用户仍然需要进行刷新。"

到目前为止Firebase方法正在运行,但我只能按服务提供商的可用性(请参阅代码)过滤我的(FirebaseUI支持的)列表视图,但我还没有想到如何按距离订购列表。

下面的代码显示了我尝试做的事情。 Person类代表服务提供者。

所以......让我们说Person类有变量Person.distance和getDistance()方法,它返回它们的位置(来自Firebase数据库)和当前存储在app用户中的位置之间的计算距离&# 39;电话。这个变量显然不能存储在数据库中并用作可比较的值,因为它是相对的,取决于用户和服务提供者的位置。

有没有办法使用回收者视图来实现这一目标呢?我会假设它将在适配器内部完成...但这已经完全包含在FirebaseUI中...而且我在编写代码时不能重新编写Android库类。谢谢你的帮助。

相关代码(工作正常......这不是问题......请先阅读帖子):

ref = FirebaseDatabase.getInstance().getReference().child("person");

    Query orderedByAvail_Query = ref.orderByChild("available").equalTo(true);

    FirebaseListAdapter<Person> fireAdapter = new FirebaseListAdapter<Person>(getActivity(),
            Person.class, R.layout.single_row, orderedByAvail_Query) {
        @Override
        protected void populateView(View v, Person person, int position) {

            TextView name_title = (TextView) v.findViewById(R.id.Nickname);
            name_title.setText(person.getNickname());

            if (person.getAvail()){
                name_title.setBackgroundColor(Color.GREEN);
            } else {
                name_title.setBackgroundColor(Color.WHITE);
            }




        }
    };

        // Arraylist<Person> tempList4Sorting = new ArrayList<Person>;

        // for (i=1 to fireAdapter.size){
        // tempList4Sorting.add(fireAdapter.getItem(i);
        // i++;
        // }

        // Collections.sort(tempList4Sorting, Person.distance, DESCENDING);

        // fireAdapter.clearItems();
        // 
        // put sorted items back into the adapter using another for loop

        // fireAdapter.notifyDataSetChanged (?)


    setListAdapter(fireAdapter);

1 个答案:

答案 0 :(得分:0)

我实现了似乎是一个有效的解决方案......虽然我肯定选择了简单而不是效率。我不认为我真的&#34;重写&#34;任何事情 - 更像是玩旧游戏,&#34;操作。&#34;无论如何......这就是我的所作所为:

1)使Person类实现Comparable,以便Collection.sort()可以工作。在compareTo()方法中,排序是通过Person.getDistance()来完成的,它只是计算运行应用程序的手机的GPS的纬度/经度与人的纬度/经度之间的距离(retreived)来自Firebase数据库)。

2)更改了FirebaseListActivity中的getItem()方法,如下所示:

@Override
public T getItem(int position) {
    Log.i("XXX", "getItem() was called");


    // put all (parsed) list items into an array

    ArrayList<Person> temp_person_list = new ArrayList();

    for (int i = 1; i<=(mSnapshots.getCount()); i++){

        temp_person_list.add((Person) parseSnapshot(mSnapshots.getItem(i-1)));

    }

    // sort the array based on distance property
    Collections.sort(temp_person_list);


    // return the originally desired position
    return (T) temp_person_list.get(position);

}

我知道原则上这很糟糕......(我确定更好的方法是在FirebaseArray类中添加另一个底层ArrayList,根据距离静默重新映射索引......但坦率地说让我的头受伤了。)

无论如何......我还考虑了另一种可能的解决方案(如Geofire) - 使用geohash而不是lat / lon。这样,只有一个(可排序的)位置字段而不是两个......并且可能会使用现有的Firebase查询方法查询实现排序(按邻近度)列表。仍在努力。