【问题标题】:Filtering FirestoreRecyclerViewOptions with SearchView使用 SearchView 过滤 FirestoreRecyclerViewOptions
【发布时间】:2021-04-14 19:07:14
【问题描述】:

我整天都在这,但似乎无法弄清楚发生了什么。我正在使用 Firebase UI 的 FireStoreRecyclerAdapter 从 firestore 获取数据并将其显示在 recyclerview 的 cardview 中。但我也想过滤搜索,以便它可以说按名称查找用户。

SearchUserAdapter.java

package com.example.cs4084_project_farm_market;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.firestore.DocumentSnapshot;
import com.squareup.picasso.Picasso;

public class SearchUserAdapter extends FirestoreRecyclerAdapter<UserModal, SearchUserAdapter.UserModalHolder> {

    private OnProfileClickListener listener;

    public interface OnProfileClickListener {
        void onProfileClick(DocumentSnapshot documentSnapshot, int position);
    }

    public SearchUserAdapter(@NonNull FirestoreRecyclerOptions<UserModal> options) {
        super(options);
    }

    @Override
    protected void onBindViewHolder(@NonNull SearchUserAdapter.UserModalHolder holder, int position, @NonNull UserModal model) {
        holder.userName.setText(String.format("%s %s", model.getFirstName(), model.getLastName()));
        holder.userDob.setText(model.getDob());
        holder.userNumber.setText(model.getNumber());
        Picasso.get().load(model.getProfileUrl())
                .fit()
                .centerCrop()
                .into(holder.profileImage);
    }

    @NonNull
    @Override
    public SearchUserAdapter.UserModalHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_search_card,
                parent, false);
        return new UserModalHolder(v);
    }

    class UserModalHolder extends RecyclerView.ViewHolder {
        TextView userName;
        TextView userDob;
        TextView userNumber;
        ImageView profileImage;

        public UserModalHolder(@NonNull View itemView) {
            super(itemView);
            userName = itemView.findViewById(R.id.search_profile_name);
            userDob = itemView.findViewById(R.id.search_profile_dob);
            userNumber = itemView.findViewById(R.id.search_profile_number);
            profileImage = itemView.findViewById(R.id.search_profile_image);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int position = getAdapterPosition();
                    if (position != RecyclerView.NO_POSITION && listener != null) {
                        listener.onProfileClick(getSnapshots().getSnapshot(position), position);
                    }
                }
            });
        }
    }
}

UserModal.java

package com.example.cs4084_project_farm_market;

public class UserModal {

    private String firstName, lastName, dob, email, address, number, profileUrl;

    public UserModal() {
    }

    public UserModal(String firstName, String lastName, String dob, String email, String address, String number, String profileUrl) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.dob = dob;
        this.email = email;
        this.address = address;
        this.number = number;
        this.profileUrl = profileUrl;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getDob() {
        return dob;
    }

    public void setDob(String dob) {
        this.dob = dob;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getProfileUrl() {
        return profileUrl;
    }

    public void setProfileUrl(String profileUrl) {
        this.profileUrl = profileUrl;
    }
}

我通过 OnCreateOptions 菜单中的搜索按钮设置查询的 SearchFragment。

package com.example.cs4084_project_farm_market;

import android.app.SearchManager;
import android.content.Context;
import android.os.Bundle;

import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SearchView;
import android.widget.Toolbar;

import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;


public class SearchFragment extends Fragment {
    private SearchView searchView = null;
    private SearchView.OnQueryTextListener queryTextListener;
    private final FirebaseFirestore db = FirebaseFirestore.getInstance();
    private final CollectionReference userRef = db.collection("users");
    private SearchUserAdapter adapter;



    public SearchFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setHasOptionsMenu(true);
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View mView = inflater.inflate(R.layout.fragment_search, container, false);

        return mView;
        // Inflate the layout for this fragment
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.search_toolbar_menu, menu);
        MenuItem searchItem = menu.findItem(R.id.app_bar_search);
        SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                Query querySearch = userRef.startAt("firstName", newText).endAt("firstName", newText+"\uf8ff").orderBy("firstName", Query.Direction.DESCENDING);

                FirestoreRecyclerOptions<UserModal> options = new FirestoreRecyclerOptions.Builder<UserModal>()
                        .setQuery(querySearch, UserModal.class)
                        .build();

                adapter = new SearchUserAdapter(options);
                RecyclerView recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
                recyclerView.setHasFixedSize(true);
                final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
                layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
                recyclerView.setLayoutManager(layoutManager);
                recyclerView.setAdapter(adapter);

                return false;
            }
        });
    }
    @Override
    public void onStart() {
        super.onStart();
        adapter.startListening();
    }


    @Override
    public void onStop() {
        super.onStop();
        adapter.stopListening();
    }

}

然后不断创建回收器适配器以存储用户键入的结果。 我认为我的 onStart 和 onStop 可能有问题。是否应该从 onCreateOptionsMenu 中调用它们?对于任何不好的代码,我对 Android Studio 还是很陌生。

【问题讨论】:

  • 你可以创建空数据的适配器,然后在适配器中创建一个更新方法来更改适配器中的数据。这样,您将只有一个适配器实例。如果您需要代码,请告诉我!
  • 请告诉我你的意思?谢谢
  • 好的,我写的是答案

标签: java android google-cloud-firestore firebaseui


【解决方案1】:

我没能跑,但干跑了它。假设除刷新外一切正常

看起来您每次都在创建适配器,这并不好。您可以更新适配器查询/选项,以便刷新。

如果不起作用,请告诉我。

public class SearchFragment extends Fragment {
    private SearchView searchView = null;
    private SearchView.OnQueryTextListener queryTextListener;
    private final FirebaseFirestore db = FirebaseFirestore.getInstance();
    private final CollectionReference userRef = db.collection("users");
    private SearchUserAdapter adapter;



    public SearchFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setHasOptionsMenu(true);
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View mView = inflater.inflate(R.layout.fragment_search, container, false);

        RecyclerView recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);

        return mView;
        // Inflate the layout for this fragment
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.search_toolbar_menu, menu);
        MenuItem searchItem = menu.findItem(R.id.app_bar_search);
        SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                Query querySearch = userRef.orderBy("firstName").startAt(newText);

                FirestoreRecyclerOptions<UserModal> options = new FirestoreRecyclerOptions.Builder<UserModal>()
                        .setQuery(querySearch, UserModal.class)
                        .build();
                if(adapter == null) {
                    adapter = new SearchUserAdapter(options);
                    recyclerView.setAdapter(adapter);
                } else {
                    adapter.updateOptions(options);
                }
                return false;
            }
        });
    }
    @Override
    public void onStart() {
        super.onStart();
        if(adapter  != null) adapter.startListening();
    }


    @Override
    public void onStop() {
        super.onStop();
        if(adapter  != null) adapter.stopListening();
    }

}

【讨论】:

  • 不幸的是,在搜索字段中输入字母时它不会崩溃。控制台显示:java.lang.IllegalArgumentException:提供给 startAt() 的参数过多。参数的数量必须小于或等于 orderBy() 子句的数量。
  • 是的,我认为现在是querySearch 的问题。你能确认一下行号是什么,是Query querySearch = userRef.startAt("firstName", ...吗?
  • 是的,就是这样
  • 您需要检查您对搜索的要求,我更新了您可以更改的代码,您不能使用多个子句
猜你喜欢
  • 2016-10-29
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 2020-10-02
  • 2019-12-28
  • 2015-08-04
  • 1970-01-01
  • 2020-10-06
相关资源
最近更新 更多