简体   繁体   English

过滤视图模型的LiveData条目填充的回收站视图

[英]Filter recycler view populated by view model's LiveData entries

I am using architecture component view model's LiveData to populate recycler view and want to add a searchview filter but couldn't find any solution. 我正在使用体系结构组件视图模型的LiveData来填充回收器视图,并希望添加一个searchview过滤器,但找不到任何解决方案。 I tried to use filterable interface in the adapter but its also not working, possible because view model doesn't let it change. 我试图在适配器中使用可过滤的接口,但它也不起作用,因为视图模型不会让它改变。

my adapter is as- 我的适配器是 -

public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.NetworksViewHolder> implements Filterable {

// Member variable to handle item clicks
final private ItemClickListener mItemClickListener;
// Class variables for the List that holds task data and the Context
private List<NetworkEntry> mNetworkEntries;
private List<NetworkEntry> mFilteredNetworkEntries = new ArrayList<>();
private Context mContext;

/**
 * Constructor for the TaskAdapter that initializes the Context.
 *
 * @param context  the current Context
 * @param listener the ItemClickListener
 */
public NetworkAdapter(Context context, ItemClickListener listener) {
    mContext = context;
    mItemClickListener = listener;
}

/**
 * Called when ViewHolders are created to fill a RecyclerView.
 *
 * @return A new TaskViewHolder that holds the view for each task
 */
@Override
public NetworksViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // Inflate the task_layout to a view
    View view = LayoutInflater.from(mContext)
            .inflate(R.layout.network_list_item, parent, false);

    return new NetworksViewHolder(view);
}

/**
 * Called by the RecyclerView to display data at a specified position in the Cursor.
 *
 * @param holder   The ViewHolder to bind Cursor data to
 * @param position The position of the data in the Cursor
 */
@Override
public void onBindViewHolder(NetworksViewHolder holder, int position) {
    // Determine the values of the wanted data
    holder.onBindData(position);
}

/**
 * Returns the number of items to display.
 */
@Override
public int getItemCount() {
    if (mNetworkEntries == null) {
        return 0;
    }
    return mNetworkEntries.size();
}

/**
 * When data changes, this method updates the list of taskEntries
 * and notifies the adapter to use the new values on it
 */
public void setNetworks(List<NetworkEntry> networkEntries) {
    mNetworkEntries = networkEntries;
    mFilteredNetworkEntries.addAll(mNetworkEntries);
    notifyDataSetChanged();
}



public List<NetworkEntry> getNetworks() {
    return mNetworkEntries;
}

@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            String charString = charSequence.toString();
            if (charString.isEmpty()) {
                mFilteredNetworkEntries = mNetworkEntries;
            } else {
                List<NetworkEntry> filteredList = new ArrayList<>();
                for (NetworkEntry row : mNetworkEntries) {

                    // name match condition. this might differ depending on your requirement
                    // here we are looking for name or phone number match
                    if (row.getNetworkName().toLowerCase().contains(charString.toLowerCase())) {
                        filteredList.add(row);
                    }
                }

                mFilteredNetworkEntries = filteredList;
            }

            FilterResults filterResults = new FilterResults();
            filterResults.values = mFilteredNetworkEntries;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            mFilteredNetworkEntries = (ArrayList<NetworkEntry>) filterResults.values;
            notifyDataSetChanged();
        }
    };
}

public interface ItemClickListener {
    void onItemClickListener(NetworkData networkData);
}


public class NetworksViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    ImageView networkLogoImageView;
    TextView networkNameTextView;
    TextView joinTextView;
    TextView commissionTextView;
    TextView minPayTextView;
    TextView payFrequencyTextView;
    TextView offerTextView;
    TextView likeTextView;
    View containerView;

    public NetworksViewHolder(View itemView) {
        super(itemView);
        networkLogoImageView = (ImageView) itemView.findViewById(R.id.iv_logo);
        networkNameTextView = (TextView) itemView.findViewById(R.id.tv_network_name);
        joinTextView = (TextView) itemView.findViewById(R.id.bt_join);
        commissionTextView = (TextView) itemView.findViewById(R.id.iv_commission);
        minPayTextView = (TextView) itemView.findViewById(R.id.tv_min_pay);
        payFrequencyTextView = (TextView) itemView.findViewById(R.id.tv_pay_frequency);
        offerTextView = (TextView) itemView.findViewById(R.id.iv_offers);
        likeTextView = (TextView) itemView.findViewById(R.id.iv_likes);
        containerView = itemView.findViewById(R.id.layoutContainer);

        joinTextView.setOnClickListener(this);
        containerView.setOnClickListener(this);
    }

    public void onBindData(int position) {
        NetworkEntry networkEntry = mNetworkEntries.get(getAdapterPosition());
        Picasso.with(mContext).load(networkEntry.getNetworkImageUrl()).into(networkLogoImageView);
        networkNameTextView.setText(networkEntry.getNetworkName());
        commissionTextView.setText(networkEntry.getNetworkCommission());
        minPayTextView.setText(mContext.getString(R.string.tv_min_pay, networkEntry.getNetworkMinPay()));
        payFrequencyTextView.setText(networkEntry.getNetworkPayFrequency());
        offerTextView.setText(networkEntry.getNetworkOffers());

    }

    @Override
    public void onClick(View view) {
        int adapterPosition = getAdapterPosition();
        NetworkEntry networkEntry = mNetworkEntries.get(adapterPosition);
        if (view.getId() == R.id.bt_join) {
            AppUtilities.openWebPage(mContext, networkEntry.getNetworkJoinUrl());
        } else {

            NetworkData networkData = new NetworkData(networkEntry);
            Log.v(NetworkAdapter.class.getSimpleName(), "Network SNO : " + networkData.getSno());
            mItemClickListener.onItemClickListener(networkData);
        }
    }

}

} }

And search view OnQueryTextListener is as - 和搜索视图OnQueryTextListener是 -

   @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.search_menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) searchItem.getActionView();
    searchView.setOnQueryTextListener(this);
    searchView.setQueryHint("Search");

    super.onCreateOptionsMenu(menu, inflater);
}


@Override
public boolean onQueryTextSubmit(String query) {
    adapter.getFilter().filter(query);
    return false;
}

@Override
public boolean onQueryTextChange(String newText) {
    adapter.getFilter().filter(newText);
    return false;
}

The problem happens because you should be using the FilteredList in your adapter, not the original list: 出现此问题的原因是您应该在适配器中使用FilteredList,而不是原始列表:

public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.NetworksViewHolder> implements Filterable {

// Member variable to handle item clicks
final private ItemClickListener mItemClickListener;
// Class variables for the List that holds task data and the Context
private List<NetworkEntry> mNetworkEntries;
private List<NetworkEntry> mFilteredNetworkEntries = new ArrayList<>();
private Context mContext;

/**
 * Constructor for the TaskAdapter that initializes the Context.
 *
 * @param context  the current Context
 * @param listener the ItemClickListener
 */
public NetworkAdapter(Context context, ItemClickListener listener) {
    mContext = context;
    mItemClickListener = listener;
}

/**
 * Called when ViewHolders are created to fill a RecyclerView.
 *
 * @return A new TaskViewHolder that holds the view for each task
 */
@Override
public NetworksViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // Inflate the task_layout to a view
    View view = LayoutInflater.from(mContext)
            .inflate(R.layout.network_list_item, parent, false);

    return new NetworksViewHolder(view);
}

/**
 * Called by the RecyclerView to display data at a specified position in the Cursor.
 *
 * @param holder   The ViewHolder to bind Cursor data to
 * @param position The position of the data in the Cursor
 */
@Override
public void onBindViewHolder(NetworksViewHolder holder, int position) {
    // Determine the values of the wanted data
    holder.onBindData(position);
}

/**
 * Returns the number of items to display.
 */
@Override
public int getItemCount() {
    if (mFilteredNetworkEntries == null) {
        return 0;
    }
    return mFilteredNetworkEntries.size();
}

/**
 * When data changes, this method updates the list of taskEntries
 * and notifies the adapter to use the new values on it
 */
public void setNetworks(List<NetworkEntry> networkEntries) {
    mNetworkEntries = networkEntries;
    mFilteredNetworkEntries.addAll(mNetworkEntries);
    notifyDataSetChanged();
}



public List<NetworkEntry> getNetworks() {
    return mFilteredNetworkEntries;
}

@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            String charString = charSequence.toString();
            List<NetworkEntry> filteredList = new ArrayList<>();
            if (charString.isEmpty()) {
                filteredList = mNetworkEntries;
            } else {
                for (NetworkEntry row : mNetworkEntries) {

                    // name match condition. this might differ depending on your requirement
                    // here we are looking for name or phone number match
                    if (row.getNetworkName().toLowerCase().contains(charString.toLowerCase())) {
                        filteredList.add(row);
                    }
                }

            }

            FilterResults filterResults = new FilterResults();
            filterResults.values = filteredList;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            mFilteredNetworkEntries = (ArrayList<NetworkEntry>) filterResults.values;
            notifyDataSetChanged();
        }
    };
}

public interface ItemClickListener {
    void onItemClickListener(NetworkData networkData);
}


public class NetworksViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    ImageView networkLogoImageView;
    TextView networkNameTextView;
    TextView joinTextView;
    TextView commissionTextView;
    TextView minPayTextView;
    TextView payFrequencyTextView;
    TextView offerTextView;
    TextView likeTextView;
    View containerView;

    public NetworksViewHolder(View itemView) {
        super(itemView);
        networkLogoImageView = (ImageView) itemView.findViewById(R.id.iv_logo);
        networkNameTextView = (TextView) itemView.findViewById(R.id.tv_network_name);
        joinTextView = (TextView) itemView.findViewById(R.id.bt_join);
        commissionTextView = (TextView) itemView.findViewById(R.id.iv_commission);
        minPayTextView = (TextView) itemView.findViewById(R.id.tv_min_pay);
        payFrequencyTextView = (TextView) itemView.findViewById(R.id.tv_pay_frequency);
        offerTextView = (TextView) itemView.findViewById(R.id.iv_offers);
        likeTextView = (TextView) itemView.findViewById(R.id.iv_likes);
        containerView = itemView.findViewById(R.id.layoutContainer);

        joinTextView.setOnClickListener(this);
        containerView.setOnClickListener(this);
    }

    public void onBindData(int position) {
        NetworkEntry networkEntry = mFilteredNetworkEntries.get(getAdapterPosition());
        Picasso.with(mContext).load(networkEntry.getNetworkImageUrl()).into(networkLogoImageView);
        networkNameTextView.setText(networkEntry.getNetworkName());
        commissionTextView.setText(networkEntry.getNetworkCommission());
        minPayTextView.setText(mContext.getString(R.string.tv_min_pay, networkEntry.getNetworkMinPay()));
        payFrequencyTextView.setText(networkEntry.getNetworkPayFrequency());
        offerTextView.setText(networkEntry.getNetworkOffers());

    }

    @Override
    public void onClick(View view) {
        int adapterPosition = getAdapterPosition();
        NetworkEntry networkEntry = mFilteredNetworkEntries.get(adapterPosition);
        if (view.getId() == R.id.bt_join) {
            AppUtilities.openWebPage(mContext, networkEntry.getNetworkJoinUrl());
        } else {

            NetworkData networkData = new NetworkData(networkEntry);
            Log.v(NetworkAdapter.class.getSimpleName(), "Network SNO : " + networkData.getSno());
            mItemClickListener.onItemClickListener(networkData);
        }
    }

}
}

The idea is that in your adapter you use the filtered list, the original list is in the adapter only to serve the purpose of being filtered by the performFiltering method. 我们的想法是,在您的适配器中使用已过滤的列表,原始列表仅在适配器中用于通过performFiltering方法进行过滤。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM