【问题标题】:Return the arraylist to original list将数组列表返回到原始列表
【发布时间】:2017-05-23 08:29:24
【问题描述】:

[On Hold] - Log.d 显示适配器类的私有成员在每次使用过滤功能时都会发生变化。即使在绑定过滤后的数据时保留原始数据。

注意:[11.01.2017] RestInfoAdapter.java 的源代码已经更改和更新(请参阅下面的第 2 项)

我一直试图通过保留原始输入列表的备份/副本来让我的搜索视图回到原始列表。但是它根本不起作用。我的这个问题包括使用自定义类的 RecyclerView 和 ArrayList。

rInf_LIST 是一个名为 RestInfo 的自定义类的 ArrayList,它存储使应用程序有用所需的信息

我一直在尝试> 1 个原始数组列表,这些数组列表绑定到 UI 元素。原始数组列表的 1 个副本和 1 个空数组列表用于存储过滤结果。完成后,与 UI 交互的 arraylist 将其值更改为过滤后的列表。如果搜索查询为空,它应该返回原始列表,这是我失败的地方

1.VacancyList.java
searchView 所在的位置(onCreate() 内)

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vacancy_list);

    srchVw = (SearchView) findViewById(R.id.search);
    srchVw.setOnQueryTextListener(new SearchView.OnQueryTextListener()
    {
        @Override
        public boolean onQueryTextSubmit(String query)
        {
            adapter.getFilter().filter(query);
            return true;
        }

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

    /*miscellaneous codes*/

    rInf_LIST = new ArrayList<>();
    new NetworkTask(this, "listfirstTime").execute();

    //Setup Recycler View with the appropriate adapter and layout.
    recyclVw = (RecyclerView) findViewById(R.id.recyclerView);
    adapter = new RestInfoAdapter(this, rInf_LIST);
    GridLayoutManager glm = new GridLayoutManager(this, 1);

    recyclVw.setLayoutManager(glm);
    recyclVw.setAdapter(adapter);

    refresh = (SwipeRefreshLayout) findViewById(R.id.refresh);
    refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
    {
        @Override
        public void onRefresh()
        {
            new Handler().post(new Runnable()
            {
                @Override
                public void run()
                {
                    new NetworkTask(VacancyList.this, "list").execute();
                    Toast.makeText(VacancyList.this, "Refreshed", Toast.LENGTH_SHORT).show();
                    refresh.setRefreshing(false);
                }
            });
        }
    });
  1. RestInfoAdapter.java 适配器类,以便RestInfo 可以在cardview 中呈现(因此是多个recyclerview)

    public class RestInfoAdapter extends RecyclerView.Adapter<RestInfoAdapter.RestInfo_ViewHolder> implements Filterable
    {
    public Filter filter;
    
    private Context context;
    private ArrayList<RestInfo> rInf_LIST;
    private ArrayList<RestInfo> filteredList;
    //Java Array starts at 0
    int selectedItemID = -1;
    
    public Context getContext()
    {return context;}
    
    public RestInfoAdapter(Context mContext, ArrayList<RestInfo> rInf)
    {
        this.context = mContext;
        rInf_LIST = rInf;
        filteredList = rInf;
        filter = new rInf_LIST_Filter();
    }
    
    @Override
    public RestInfo_ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View itemVw = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
        return new RestInfo_ViewHolder(itemVw);
    }
    
    //Binds 1 RestInfo to the UI elements
    @Override
    public void onBindViewHolder(final RestInfo_ViewHolder holder, int position)
    {
        RestInfo rInf = filteredList.get(position);
        holder.rName.setText(rInf.getRestName());
        holder.rLot.setText(rInf.getRestLot());
        holder.rVacancy_PROGBAR.setProgress(rInf.getResVacant());
        holder.progBarVal.setText(Integer.toString(rInf.getResVacant()/10));
    }
    
    @Override
    public int getItemCount()
    {
        return rInf_LIST.size();
    }
    
    @Override
    public Filter getFilter()
    {
        return filter;
    }
    
    private class rInf_LIST_Filter extends Filter
    {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence)
        {
            FilterResults results = new FilterResults();
            ArrayList<RestInfo> temp = new ArrayList<>();
    
            if(charSequence.length() == 0)
                temp.addAll(rInf_LIST);
            else
            {
                String filtrate = charSequence.toString().toLowerCase().trim();
    
                for(int count = 0; count < rInf_LIST.size(); count++)
                {
                    if(rInf_LIST.get(count).getRestName().toLowerCase().contains(filtrate))
                        temp.add(rInf_LIST.get(count));
                }
            }
    
            results.values = temp;
            results.count = temp.size();
    
            return results;
        }
    
        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults)
        {
            Log.d("charSequence : ", Integer.toString(charSequence.length()));
            if(true)
            {
                filteredList.clear();
                filteredList.addAll((ArrayList<RestInfo>) filterResults.values);
                notifyDataSetChanged();
            }
        }
    }
    
    public class RestInfo_ViewHolder extends RecyclerView.ViewHolder
    {
        public TextView rName, rLot, progBarVal;
        public ProgressBar rVacancy_PROGBAR;
    
        public RestInfo_ViewHolder(final View itemView)
        {
            super(itemView);
    
            rName = (TextView)itemView.findViewById(R.id.txtVw_RestName);
            rLot = (TextView)itemView.findViewById(R.id.txtVw_RestLot);
            progBarVal = (TextView)itemView.findViewById(R.id.progBarTextValue);
    
            rVacancy_PROGBAR = (ProgressBar)itemView.findViewById(R.id.progBar);
    
            itemView.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View view) {
                    selectedItemID = getAdapterPosition();
                    Intent intent = new Intent(context, RestaurantInfo.class);
    
                    intent.putExtra("selected_Rest", filteredList.get(selectedItemID));
                    context.startActivity(intent);
                }
            });
        }
    }
    

    }

  2. RestInfo的数据结构及获取restName的相关方法。

    //Displayed in CardView (and RestaurantInfo)
    //protected ImageView imgVw;
    protected String restName;
    protected String restLot;
    protected String restLoc;
    protected int restVacant;
    
    //Displayed in RestaurantInfo
    protected String restType;
    protected String restNo;
    protected String restEmail;
    
    //Displayed for Admin
    protected String restOwn;
    protected int restID;
    
    //Status
    private boolean objIS_EMPTY = true;
    
    public String getRestName(){
        return restName;
    }
    

编辑 1

Logcat 使用 Log.D 这是在publishResults 方法中完成的。此日志记录的目的是检查列表是否为空。

[PRE] 标签在if(filterResults.count &gt; 0) 之前。
[POST] 标签位于if(filterResults.count &gt; 0) //evaluates falseclear() 以及addAll() 方法之后

01-09 14:33:06.357 23159-23159/fyp.inrestaurant D/[PRE] filterResults: 0

01-09 14:33:06.357 23159-23159/fyp.inrestaurant D/[PRE] rInf_LIST: 5

01-09 14:33:06.357 23159-23159/fyp.inrestaurant D/[PRE] rInf_LIST_cpy: 5

01-09 14:33:06.367 23159-23159/fyp.inrestaurant D/[POST] filterResults: 0

01-09 14:33:06.367 23159-23159/fyp.inrestaurant D/[POST] rInf_LIST: 0

01-09 14:33:06.367 23159-23159/fyp.inrestaurant D/[POST] rInf_LIST_cpy: 0

编辑 2

这适用于编辑 1 中的条件为真时

01-09 14:39:31.027 23159-23159/fyp.inrestaurant D/[PRE] filterResults: 3

01-09 14:39:31.027 23159-23159/fyp.inrestaurant D/[PRE] rInf_LIST: 5

01-09 14:39:31.027 23159-23159/fyp.inrestaurant D/[PRE] rInf_LIST_cpy: 5

01-09 14:39:31.027 23159-23159/fyp.inrestaurant D/[POST] filterResults: 3

01-09 14:39:31.027 23159-23159/fyp.inrestaurant D/[POST] rInf_LIST: 3

01-09 14:39:31.027 23159-23159/fyp.inrestaurant D/[POST] rInf_LIST_cpy: 3

编辑 3

添加了用于记录publishResults的更新代码

protected void publishResults(CharSequence charSequence, FilterResults filterResults)
    {
        Log.d("[PRE] filterResults", Integer.toString(filterResults.count)+"\n");
        Log.d("[PRE] rInf_LIST", Integer.toString(rInf_LIST.size())+"\n");
        Log.d("[PRE] rInf_LIST_cpy", Integer.toString(rInf_LIST_cpy.size())+"\n");
        if(filterResults.count > 0)
        {
            rInf_LIST.clear();
            rInf_LIST.addAll((ArrayList<RestInfo>) filterResults.values);
            Log.d("[POST] filterResults", Integer.toString(filterResults.count)+"\n");
            Log.d("[POST] rInf_LIST", Integer.toString(rInf_LIST.size())+"\n");
            Log.d("[POST] rInf_LIST_cpy", Integer.toString(rInf_LIST_cpy.size())+"\n");
            notifyDataSetChanged();
        }
        else
        {
            rInf_LIST.clear();
            rInf_LIST.addAll(rInf_LIST_cpy);
            Log.d("[POST] filterResults", Integer.toString(filterResults.count)+"\n");
            Log.d("[POST] rInf_LIST", Integer.toString(rInf_LIST.size())+"\n");
            Log.d("[POST] rInf_LIST_cpy", Integer.toString(rInf_LIST_cpy.size())+"\n");
            notifyDataSetChanged();
        }
    }

编辑 4

添加了新的代码建议

public RestInfoAdapter(Context mContext, ArrayList<RestInfo> rInf)
{
    this.context = mContext;
    rInf_LIST = rInf;
    rInf_LIST_cpy = new ArrayList<>(rInf);
    filteredList = new ArrayList<>();
    filter = new rInf_LIST_Filter();
}

日志没有显示改进(这是错误的)

01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[PRE] filterResults: 0

01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[PRE] rInf_LIST: 5

01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[PRE] rInf_LIST_cpy: 0

01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[POST] filterResults: 0

01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[POST] rInf_LIST: 0

01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[POST] rInf_LIST_cpy: 0


当条件应该为真时。 (5个数据集中有3个包含字符s)

01-09 14:53:01.427 8198-8198/fyp.inrestaurant D/[PRE] filterResults: 0

01-09 14:53:01.427 8198-8198/fyp.inrestaurant D/[PRE] rInf_LIST: 0

01-09 14:53:01.427 8198-8198/fyp.inrestaurant D/[PRE] rInf_LIST_cpy: 0

01-09 14:53:01.427 8198-8198/fyp.inrestaurant D/[POST] filterResults: 0

01-09 14:53:01.427 8198-8198/fyp.inrestaurant D/[POST] rInf_LIST: 0

01-09 14:53:01.427 8198-8198/fyp.inrestaurant D/[POST] rInf_LIST_cpy: 0

编辑 5

由于对 rInf_List 的取值存在疑问,这里是onPostExecute() 的代码和相关方法。

P / S @beeb,我犯了一个错误,该方法不在onpostexecute中,而是在processfinish中,因为NetworkTask是它自己的另一类(因为有多个活动需要执行NetworkTask,我做了一个类来减少代码库)

tl:博士;代码版本:processFinish 将输出设置为 JSON 数组。然后,该数组将通过自定义转换方法 JSONArray_RestInf() 将其成员分配给 temp(RestInfo 类型)。这个临时变量将通过 RestInfo_ArrLst() 方法添加到全局变量 rInf_List 中。如果添加了新项目,它将调用 notifyItemAdded(int position)。如果之前的 item 相同,但是给出了额外的数据,那么 notifyItemChanged 将在相应的位置被调用。

@Override
public void processFinish(String output)
{
    boolean firstTime = Boolean.parseBoolean(output.substring(0, output.indexOf('e') + 1));
    output = output.substring(output.indexOf('e') + 1);

    if (!output.isEmpty())
    {
        try
        {
            jsArr = new JSONArray(output);

            for (int ctr = 0; ctr < jsArr.length(); ctr++)
            {
                RestInfo temp = JSONArray_RestInf(ctr);
                RestInfo_ArrLst(temp, firstTime);
            }
            Log.w("Size...", Integer.toString(rInf_LIST.size()));
        }
        catch (JSONException e)
        {
            e.printStackTrace();

        }
    }
    else
        Toast.makeText(VacancyList.this, "Failed to retrieve list", Toast.LENGTH_SHORT).show();
}

//Converts the JSONArray to RestInfo
private RestInfo JSONArray_RestInf(final int index)
{
    RestInfo tempInf;

    try
    {
        ArrayList<String> tempArrLst = new ArrayList<>();

        //Converts JSONArray to ArrayList of strings
        for (String ctr : ELEMENTS)
        {
            tempArrLst.add(jsArr.getJSONObject(index).get(ctr).toString());
        }

        tempInf = new RestInfo(Integer.parseInt(tempArrLst.get(0)), tempArrLst.get(1), tempArrLst.get(2), tempArrLst.get(3), tempArrLst.get(4), Integer.parseInt(tempArrLst.get(5)), tempArrLst.get(6), tempArrLst.get(7), tempArrLst.get(8));

        return tempInf;
    }
    catch (JSONException e)
    {
        e.printStackTrace();

        return new RestInfo(0, "", "", "", "", 0, "", "", "");
    }
}

//Adds the temporary restaurant info to the array.
private void RestInfo_ArrLst(RestInfo tempInf, boolean firstT)
{
    if (!tempInf.getEMPTY_Status())
    {
        if (firstT)
        {
            rInf_LIST.add(tempInf);
            adapter.notifyDataSetChanged();
        }
        else
        {
            boolean hasSameField;
            ArrayList<Boolean> hasChanged = new ArrayList<>(), isSimilar = new ArrayList<>();
            ArrayList<Integer> changedPos = new ArrayList<>();

            //Loop to check for duplicates
            for (int ctr = 0; ctr < rInf_LIST.size(); ctr++)
            {
                hasSameField = (tempInf.checkFields(rInf_LIST.get(ctr)));
                if (tempInf.getRestID() == rInf_LIST.get(ctr).getRestID() && !hasSameField)
                {
                    rInf_LIST.set(ctr, tempInf);
                    changedPos.add(ctr);
                    hasChanged.add(true);
                }
                else if (tempInf.getRestID() == rInf_LIST.get(ctr).getRestID() && hasSameField)
                {
                    isSimilar.add(true);
                }
            }

            for(int ctr = 0; ctr < hasChanged.size(); ctr++)
            {
                if (!hasChanged.get(ctr)&& !isSimilar.get(ctr))
                {
                    rInf_LIST.add(tempInf);
                    adapter.notifyItemInserted(adapter.getItemCount() - 1);
                }
                else if (hasChanged.get(ctr))
                {
                    adapter.notifyItemChanged(changedPos.get(ctr));
                }
            }
        }
    }
}

【问题讨论】:

    标签: java android


    【解决方案1】:

    这将解决您的问题:

    public RestInfoAdapter(Context mContext, ArrayList<RestInfo> rInf)
    {
        this.context = mContext;
        rInf_LIST = rInf;
        rInf_LIST_cpy = new ArrayList<>(rInf);  // Create a new object. You don't want to use the same reference. :)
        filteredList = new ArrayList<>();
        filter = new rInf_LIST_Filter();
    }
    

    【讨论】:

    • 我正要问它有什么不同。但是您编辑了,它仍然无法正常工作。我认为新代码正在创建一个新的数组列表,其中包含我想要使用的数组列表(2 级数组列表而不是 1 级)。
    • rInf_LIST_cpy 列表创建所有对象的新副本。因此,当您执行rInf_LIST.clear() 时,rInf_LIST_cpy 应该保持不变。你能调试publishResults 方法,看看所有列表的大小是多少?
    • 如果您的意思是记录它们,我在帖子上添加了新的编辑。好像出了点问题。
    • 我看到了你的日志。这个问题应该通过我给你的代码来解决。请您重新检查一下。
    • 在您的日志中显示此01-09 14:51:26.687 8198-8198/fyp.inrestaurant D/[PRE] rInf_LIST_cpy: 0。为什么 PRE 中的列表大小为 0?
    【解决方案2】:

    你在哪里使用这种代码来创建一个新列表:filteredList.add(rInf_LIST_cpy.get(count));

    尝试创建一个新对象 RestInfo 并将值保存到该对象,然后添加到列表中

    【讨论】:

    • 那部分代码正在运行。不是的部分是当我进行一个应该返回原始列表的空查询时。
    【解决方案3】:

    首先你用一个空列表初始化你的适配器:

    rInf_LIST = new ArrayList<>(); // you create an empty list
    new NetworkTask(this, "listfirstTime").execute();
    
    //Setup Recycler View with the appropriate adapter and layout.
    recyclVw = (RecyclerView) findViewById(R.id.recyclerView);
    adapter = new RestInfoAdapter(this, rInf_LIST); // at this point your list is already empty
    

    我们看不到你在哪里添加你的项目(我认为它在 onPostExecute()NetworkTask 对吗?)。

    第二:您必须创建原始列表的副本,因为您不想在过滤时修改原始列表:rInf_LIST_cpy = new ArrayList&lt;&gt;(rInf);

    第三:在您的过滤器中,您只需要这样做:

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
      rInf_LIST.clear();
      rInf_LIST.addAll((ArrayList<RestInfo>) filterResults.values);
      notifyDataSetChanged();
    }
    

    因为您已经在performFiltering() 的结果中添加了正确的对象

    有关更多信息,请查看此链接的接受答案:Add a search filter on RecyclerView with Cards?

    【讨论】:

    • 该值是从网络任务中的服务器检索的。在 onpostexecute 中调用 notifyItemAdd 或 DataSetChanged。我已经尝试过您的解决方案,但它不起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2019-12-18
    • 1970-01-01
    • 2012-11-22
    • 2019-10-25
    • 1970-01-01
    相关资源
    最近更新 更多