【发布时间】: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);
}
});
}
});
-
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); } }); } }}
-
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 > 0) 之前。
[POST] 标签位于if(filterResults.count > 0) //evaluates false 和clear() 以及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));
}
}
}
}
}
【问题讨论】: