簡體   English   中英

我的RecyclerView過濾后不斷重置

[英]My RecyclerView keeps getting reset after filtering

我有一個可正常使用的RecyclerView,我需要實現一個搜索欄。 我設法用EditText和TextWatcher創建了一個搜索欄,但是存在以下問題:

通常,我的列表根據當前項目的位置傳遞數據,並且當我過濾列表時,位置當然會被弄亂。

我遵循了一些指南,發現了解決方法:

private void filter(String text){
    ArrayList<Item> filteredList = new ArrayList<>();

    for (Item item : mList ) {
        if(item.getName().toLowerCase().contains(text.toLowerCase())) {
            filteredList.add(item);
        }
    }
    mListAdapter.filterList(filteredList);

    //when the app is done filtering, it clears the existing ArrayList and it adds just the filtered Items

    mList.clear();
    mList.addAll(filteredList);
}

這種方法的問題是,當發生mList.clear()時,我會丟失所有數據,僅保留過濾后的數據。 然后,當我從搜索欄中刪除文本時,我所擁有的只是一個空的RecyclerView。

我曾想過在EditText為null時嘗試將列表重置為原始狀態,但是我不知道該怎么做,而且也不理想。

誰能想到解決此問題的方法? 我真的很絕望:D

我的RecyclerView類:

public class ListFragment extends Fragment {

static final String EXTRA_NAME = "monumentname";
static final String EXTRA_NUMBER = "monumentnumber";
static final String EXTRA_REGION = "monumentregion";
static final String EXTRA_REGION2 = "monumentregion2";
static final String EXTRA_TOWN = "monumenttown";
static final String EXTRA_DESCRIPTION = "monumentdescription";
static final String EXTRA_WEB = "web";

private ListAdapter mListAdapter;
private ArrayList<Item> mList;
private RequestQueue mRequestQueue;
private Context mContext;
private InternetCheck internetCheck = new InternetCheck();


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable final Bundle savedInstanceState) {
    View rootview = inflater.inflate(R.layout.fragment_list, container, false);

    RecyclerView mRecyclerView = rootview.findViewById(R.id.recycler_view);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    Button syncData = rootview.findViewById(R.id.sync_button);
    final ProgressBar progressBar = rootview.findViewById(R.id.progressbar);
    EditText editText = rootview.findViewById(R.id.edittext);

    editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            filter(s.toString());
        }
    });

..........some other irrelevant stuff here


    mListAdapter.setOnItemClickListener(new ListAdapter.OnItemClickListener() {
        @Override
        public void onItemClick(int position) {
            Intent detailIntent = new Intent(getActivity(), SingleItem.class);
            Item clickedItem = mList.get(position);

            detailIntent.putExtra(EXTRA_NAME, clickedItem.getName());
            detailIntent.putExtra(EXTRA_NUMBER, clickedItem.getNumber());
            detailIntent.putExtra(EXTRA_REGION, clickedItem.getRegion());
            detailIntent.putExtra(EXTRA_REGION2, clickedItem.getRegion2());
            detailIntent.putExtra(EXTRA_TOWN, clickedItem.getTown());
            detailIntent.putExtra(EXTRA_DESCRIPTION, clickedItem.getDescription());
            detailIntent.putExtra(EXTRA_WEB, clickedItem.getWeb());

            startActivity(detailIntent);
        }
    });


    return rootview;
}

.......some onCreateView and stuff like that here

public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    loadData();
    mListAdapter = new ListAdapter(mContext, mList);
    mRequestQueue = Volley.newRequestQueue(mContext);

}

private void parseJSON() {

    JsonObjectRequest request = new JsonObjectRequest("http://192.168.0.105/sestavsisvujsvetweb/api/seznammagnetek", null, new Response.Listener<JSONObject>() {

.....parsing my JSON here



    mRequestQueue.add(request);

}

private CharSequence removeHtmlFrom(String html) {
    return new HtmlCleaner().clean(html).getText();
}

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


private void saveData() {
    SharedPreferences sharedPreferences = getContext().getSharedPreferences("shared preferences", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    Gson gson = new Gson();
    String json = gson.toJson(mList);
    editor.putString("seznam magnetek", json);
    editor.apply();
}

private void loadData() {
    SharedPreferences sharedPreferences = getContext().getSharedPreferences("shared preferences", MODE_PRIVATE);
    Gson gson = new Gson();
    String json = sharedPreferences.getString("seznam magnetek", null);
    Type type = new TypeToken<ArrayList<Item>>() {
    }.getType();
    mList = gson.fromJson(json, type);

    if (mList == null || mList.isEmpty()) {
        Toast.makeText(getContext(), "Seznam magnetek je prázdný. Aktualizujte prosím data z databáze.", Toast.LENGTH_SHORT).show();
        mList = new ArrayList<>();
    }
}

private void filter(String text) {
    ArrayList<Item> filteredList = new ArrayList<>();

    for (Item item : mList) {
        if (item.getName().toLowerCase().contains(text.toLowerCase())) {
            filteredList.add(item);
        }
    }
    mListAdapter.filterList(filteredList);
    mList.clear();
    mList.addAll(filteredList);
}

}

您在這里有2個潛在問題:

  1. 將filteredList傳遞給mListAdapter之后,必須調用adapter.notifyDataSetChanged notifyDataSetChanged來使列表視圖無效。
  2. 此外,將過濾列表添加到適配器后,無需清除mList 由於loadData僅被調用一次,因此如果您第一次清除它,則列表中只剩下已過濾的項目。 即使刪除了過濾器字符串,該項目也不會添加回mList

請嘗試添加以下內容:

private void filter(String text){
    ArrayList<Item> filteredList = new ArrayList<>();

    for (Item item : mList ) {
        if(item.getName().toLowerCase().contains(text.toLowerCase())) {
            filteredList.add(item);
        }
    }
    mListAdapter.filterList(filteredList);
    mListAdapter.notifyDataSetChanged();
}

在您的RecyclerView Adapter類中,添加一個ValueFilter和一個保存先前數據的ValueFilter

private ValueFilter valueFilter;
private ArrayList<Item> mListFull;  // this arraylist contains previous data.
private ArrayList<Item> mList;


public Filter getFilter() {
        if (valueFilter == null) {
            valueFilter = new ValueFilter();
        }
        return valueFilter;
}

ValueFilter將顯示cannot resolve symbol 'ValueFilter' ,因此創建一個名為ValueFilter的類。

創建類ValueFilter

private class ValueFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        String str = constraint.toString().toUpperCase();
        Log.e("constraint", str);
        FilterResults results = new FilterResults();

        if (constraint.length() > 0) {
            ArrayList<Item> filterList = new ArrayList<>();
            for (int i = 0; i < mListFull.size(); i++) {
                if ((mListFull.get(i).getName().toUpperCase())
                        .contains(constraint.toString().toUpperCase())) {
                    Item item = mListFull.get(i);
                    filterList.add(item);
                }
            }
            results.count = filterList.size();
            results.values = filterList;
        } else {
            results.count = mListFull.size();
            results.values = mListFull;
        }
        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        mList = (ArrayList<Item>) results.values;
        notifyDataSetChanged();
    }
}

現在在您的EditText TextChangedListener onTextChanged中

 editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            youradapter.getFilter().filter(charSequence.toString());  //Add this (change youradapter with the name of your recyclerview adapter.)
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });

你犯了一個愚蠢的錯誤。 您還要清除並在實際列表中添加新值。 你不應該那樣做。

  • 您只應解析在過濾器中獲得的新列表[filterlist]
  • 並從afterTextChanged和加載項onTextChanged中刪除以調用filter(s.toString())

例子:-

第1步: 在課堂上更改通話過濾器

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        filter(s.toString());
    }

    @Override
    public void afterTextChanged(Editable s) {
//            filter(s.toString());
    }
});

第2步: 刪除過濾功能中該行下方的內容。

mList.clear();
mList.addAll(filteredList);

步驟3: 在您的適配器類中:

public void filterlist(List<Item> name) {
    this.Listname = name;
    notifyDataSetChanged();
}

要全面了解Recycleview中的搜索,請參考以下鏈接:-

如何填充recyclerView

嗨Etoile,

我們的樣本問題:

假設我們有一個相框,我們要做的就是將其一部分擦除一段時間,然后再顯示整個相框。

可能的解決方案:

我們可以將整個Frame的實例保存在某個地方,假設A = Frame的實例,然后我們可以說B =A。因此,我們可以將B用作主框架,將A用作備用框架。 在我們通過擦除一段時間來修改B幀之后,可以很容易地返回到先前的狀態,方法是說我們不想再次修改,則讓B =A。因為我們的A仍然保持其狀態。

代碼示例實現 (盡管已修改)

private ArrayList<Item> mList; //Aka A from our solution above
private ArrayList<Item> filteredList = new ArrayList<>();// Aka B from our solution above

public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mListAdapter = new ListAdapter(mContext, filteredList);
    loadData();

editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2{
            filter(s.toString()); // I feel like it will be faster filtering from here
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });
}

/* Here, we load the lists of items and notify our adapter of the changes, the last time in this function does the nofity */
private void loadData() {
    SharedPreferences sharedPreferences = getContext().getSharedPreferences("shared preferences", MODE_PRIVATE);
    Gson gson = new Gson();
    String json = sharedPreferences.getString("seznam magnetek", null);
    mList = gson.fromJson(json, new TypeToken<ArrayList<Item>>(){}.getType(););

    if (mList == null || mList.isEmpty()) {
        Toast.makeText(getContext(), "Seznam magnetek je prázdný. Aktualizujte prosím data z databáze.", Toast.LENGTH_SHORT).show();
        mList = new ArrayList<>();
    }

    filteredList = mList;
    mListAdapter.notifyDataSetChanged();
}

//So, if nothing is typed in the EditText, we simply want to reset back to the //previous state else do as appropriate i.e modify filteredList and notify adapter
private void filter(String text){
    if(text.isEmpty()){
      filteredList = mList;
      mListAdapter.notifyDataSetChanged();
    }else{
      filteredList.clear();

      for (Item item : mList ) {
        if(item.getName().toLowerCase().startsWith(text.toLowerCase())) {
            filteredList.add(item); //Aka B from our solution above
        }
      }

//we have cleared and modified filteredList, all we need to do if notify adapter.
      mListAdapter.notifyDataSetChanged();
    }
}

請提交錯誤(如有),我們可以進行更正。 快樂的編碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM