Я пытаюсь вытащить список идентификаторов друзей из моей базы данных firebase в свое приложение, а затем ищу любые дополнительные данные, связанные с игроком (такие как имя пользователя, онлайн-статус и т. Д.), Просматривая их запись в разделе «пользователи» с помощью их уникальный идентификатор

Моя схема выглядит следующим образом:

{friends
    {
      "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
        "-KR0aTQGT6pfRfB5qIUz" : {
          "friend_id" : "6vFVAAQfwiYERl03C3lzxdPjnEp2"
        },
        "-KR0aaMAOS3FWOAosBmo" : {
          "friend_id" : "kxrQFVjGv0XUHyV5N764Nq50Q3J3"
        }
      }
    }
}

Первый уникальный идентификатор - это идентификатор игрока, который позволяет запрашивать список его друзей. Дочерние объекты, которые представляют собой ID отношений, а friend_id под ним показывает ID других игроков (друзей).

Схема пользователя выглядит следующим образом:

{
  "6vFVAAQfwiYERl03C3lzxdPjnEp2" : {
    "emailAddress" : "b@b.com",
    "level" : 1,
    "userName" : "steve"
  },
  "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
    "emailAddress" : "a@a.com",
    "level" : 1,
    "userName" : "bob"
  },
  "kxrQFVjGv0XUHyV5N764Nq50Q3J3" : {
    "emailAddress" : "bg@b.com",
    "level" : 1,
    "userName" : "tim"
  },
  "rNtYvwF8LBhTRM1Wk8ybBJyrFIg2" : {
    "emailAddress" : "c@c.com",
    "level" : 1,
    "userName" : "test account"
  }
}

Теперь в моем приложении я могу успешно извлечь все записи friend_id, но не знаю, как потом развернуться и получить дополнительную информацию о друге с помощью этого идентификатора. В идеале я мог бы запросить каждого друга по одному по их уникальному идентификатору игрока и заполнить имеющийся у меня фрагмент списка друзей с помощью firebaseListAdapter.

Вот как я извлекаю идентификаторы друзей и заполняю объект списка.

ValueEventListener friendListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                friendIdList.clear();
                for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
                    String friend_id = (String) messageSnapshot.child("friend_id").getValue();
                    friendIdList.add(friend_id);
                }

            }
            @Override
            public void onCancelled(DatabaseError databaseError) {}
        };
        mDatabase.addValueEventListener(friendListener);

Может ли кто-нибудь помочь мне выяснить, как лучше всего получить всю эту дополнительную информацию о друзьях после получения идентификаторов из первоначального запроса?

1
Dportology 8 Сен 2016 в 02:01

5 ответов

Лучший ответ

Итак, я просто соединю ответы Мэтью Берга и пастилли. Основываясь на вашем вопросе и комментариях, я думаю, что вместе они обеспечивают решение, которое вы ищете.

Структура данных

Структура, которую вы используете для определения местоположения пользователей, мне нравится, поэтому я бы сказал, что вы можете оставить ее как есть:

{
    users: {
       "6vFVAAQfwiYERl03C3lzxdPjnEp2" : {
            "emailAddress" : "b@b.com",
            "level" : 1,
            "userName" : "steve"
        },
       "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
            "emailAddress" : "a@a.com",
            "level" : 1,
            "userName" : "bob"
        }

    }
} 

Что касается местоположения ваших друзей, я согласен со структурой, данной Мэтью Бергом:

{
    friends : {
        "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
            "6vFVAAQfwiYERl03C3lzxdPjnEp2" : true,
            "kxrQFVjGv0XUHyV5N764Nq50Q3J3" : true
        }
    }
}

Просто к сведению, вам не нужно использовать логическое значение с этой структурой. Вы можете использовать любой разрешенный тип данных в качестве значения для каждого ключа. В этом случае важен ключ, значение - просто заполнитель, потому что Firebase не допускает ключей с нулевыми значениями. Тем не менее, если вы найдете причину использовать более полезное значение, вы можете это сделать. На мой взгляд, использование логического значения делает структуру более читаемой для членов команды или тех, кто может следовать за вами.

Получение ваших данных

Есть несколько способов сделать запрос к списку друзей и получить данные для каждого пользователя. Поскольку вы упомянули об использовании FirebaseListAdapter в своем вопросе, я соглашусь с этим. Тот же шаблон можно использовать с FirebaseRecyclerAdapter, если вы хотите использовать вместо этого RecyclerView с FirebaseUI. Основные шаги:

  1. Создайте DatabaseReference, который указывает на местоположение пользователя чей список друзей вы хотите.

  2. Создайте DatabaseReference, указывающий на местоположение ваших пользователей

  3. Создайте свой FirebaseListAdapter.

  4. Когда вы переопределяете populateView, получите ключ для каждого элемента

  5. Используйте addListenersingleValueEvent(), чтобы получить информацию о каждом из друзей и заполнить элементы строки списка с данными из этот запрос.

  6. В пределах onDataChange значения прослушиватель событий использует информацию для каждого пользователя для заполнения представлений для каждого элемента списка.

DatabaseReference mFriendsRef = FirebaseDatabase.getInstance().getReference().child("friends").child(someUserID;

DatabaseReference mUsersRef = FirebaseDatabase.getInstance().getReference().child("users");

...

mAdapter = new FirebaseListAdapter<YourModel>(this, YourModel.class, android.R.your_layout, mFriendsRef) {
    @Override
    protected void populateView(final View view, YourModel model, int position) {
        String key = getRef(position).getKey();
        mUsersRef.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        //get data from dataSnapshot and bind to views for each list item 
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
        });     
    }
};

messagesView.setAdapter(mAdapter);

Ознакомьтесь с комментарием по этому вопросу, чтобы узнать о проблемах производительности при использовании этого подхода: Android Firebase - Денормализованные запросы с использованием FirebaseUI

1
Community 23 Май 2017 в 12:19

Вы можете использовать ChildEventListener, чтобы получить всех друзей, затем в своем populateview или onBindViewHolder используйте ValueEventListener, чтобы получить все данные друга. также попробуйте использовать FirebaseRecyclerView вместо FirebaseListView

3
pastillas 8 Сен 2016 в 07:11

Да согласен, даже у меня такое же замешательство. Мы боремся с запросом Contains [*, *, *].

Даже у меня похожая проблема

/ Пользователи {
"uuid1": {
data1: "значение1"
данные2: "значение2"
}
"uuid2": {
data1: "значение1"
данные2: "значение2"
}
}

/ Друзья: {
uuid1: {
"uuid2": правда
....
}
uuid2: {
"uuid1": верно
...
}
}

Мой запрос - это запрос списка только моих друзей и представление их данных («/ Пользователь») с помощью FirebaseRecyclerViewAdapter.

2
OS Idris 8 Сен 2016 в 06:32

Я бы предложил другую структуру данных. Вот оно основано на ваших данных:

{
    friends : {
        "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
            "6vFVAAQfwiYERl03C3lzxdPjnEp2" : true,
            "kxrQFVjGv0XUHyV5N764Nq50Q3J3" : true
        }
    }
}

Затем оберните каждый из них и поднимите их индивидуальные профили.

2
Mathew Berg 8 Сен 2016 в 14:51

Извините, сэр, я не знаю, будет ли он работать на FirebaseUI, но вот мой код, который, как мне кажется, имеет ту же проблему, а также такое же решение, он отобразит список подписчиков пользователя, а затем, если подписчик щелкнул, он откроется и передаст идентификатор элемента, на который щелкнули другие действия. Я не использовал FirebaseUI.

public class FollowersAdapter extends RecyclerView.Adapter<FollowersAdapter.FollowersHolder>{
public ArrayList<Follower> followers;

public void addFollower(Follower follower) {
    followers.add(follower);
    notifyItemInserted(getItemCount());
}

public FollowersAdapter(Context context) {
    this.followers = new ArrayList<>();
    mDatabase = FirebaseDatabase.getInstance().getReference();
    this.fUser = FirebaseAuth.getInstance().getCurrentUser();

    mDatabase.child("follower").child(fUser.getUid()).addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            Follower follower = dataSnapshot.getValue(Follower.class);
            addFollower(follower);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            Follower follower = dataSnapshot.getValue(Follower.class);
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

@Override
public FollowersHolder onCreateViewHolder(ViewGroup parent, int position) {
    View view = inflater.inflate(R.layout.followers_model, parent, false);
    FollowersHolder holder = new FollowersHolder(view);
    return holder;
}

@Override
public void onBindViewHolder(final FollowersHolder holder, final int position) {
    Query userQuery = mDatabase.child("users").child(followers.get(position).getId());
    userQuery.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            user = dataSnapshot.getValue(User.class);

            holder.name.setText(user.getName());

            final Bundle extras = new Bundle();
            extras.putString(EXTRAS_POSTER_ID, user.getId());

            holder.cont.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!fUser.getUid().equals(user.getId())) {
                        Intent intent = new Intent(context, ViewUserProfile.class);
                        intent.putExtra(EXTRAS_BUNDLE, extras);
                        context.startActivity(intent);
                    }
                }
            });
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

@Override
public int getItemCount() {
    return followers.size();
}

class FollowersHolder extends RecyclerView.ViewHolder {
    View cont;
    TextView name;

    public FollowersHolder(View itemView) {
        super(itemView);

        cont = itemView.findViewById(R.id.cont_followers);
        name = (TextView) itemView.findViewById(R.id.tv_followers_name);
    }
}

}

Вы получаете данные с помощью childEventListener, затем в onBindViewHolder или populateView добавляете onClickListener и передаете идентификатор, когда он щелкает, для другого действия. извините, сэр, я новичок, лол :)

1
pastillas 9 Сен 2016 в 13:21