jjzjj

android - 过滤由 View 模型的 LiveData 条目填充的回收器 View

coder 2023-12-22 原文

我正在使用架构组件 View 模型的 LiveData 来填充回收器 View ,并想添加一个搜索 View 过滤器,但找不到任何解决方案。 我尝试在适配器中使用可过滤接口(interface),但它也不起作用,可能是因为 View 模型不允许它更改。

我的适配器是-

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);
        }
    }

}

搜索 View 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;
}

最佳答案

出现问题是因为您应该在适配器中使用 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);
        }
    }

}
}

想法是在您的适配器中使用过滤列表,原始列表在适配器中仅用于通过 performFiltering 方法进行过滤的目的。

关于android - 过滤由 View 模型的 LiveData 条目填充的回收器 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50638839/

有关android - 过滤由 View 模型的 LiveData 条目填充的回收器 View的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  3. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  4. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  5. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  6. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  9. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  10. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

随机推荐