Android filterResults() 显示重复项

Android filterResults() showing duplicate items

我不知道为什么会出现此错误。 我实施了 filterResults()。 实际上,当我第一次在编辑文本中搜索并单击它时,它工作正常。 然后当我回来再次搜索某个城市时,它显示了 2 个相同的条目。我已经添加了屏幕截图。 然后当我第三次回来搜索时,我为每个搜索的城市得到了 3 个相同的条目。

My java class:


package com.wordpress.myselfnikunj.cofighter;

import android.os.Bundle;

import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;

import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import com.wordpress.myselfnikunj.cofighter.Adapters.CountryListAdapter;
import com.wordpress.myselfnikunj.cofighter.Model.CountryNamesModel;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class AffectedCountriesFragment extends Fragment {

    EditText searchEditText;
    ListView listView;

    public static List<CountryNamesModel> countryNamesModelList = new ArrayList<>();
    CountryNamesModel countryNamesModel;
    CountryListAdapter countryListAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_affected_countries, container, false);

        searchEditText = (EditText) view.findViewById(R.id.searchEditText);
        listView = (ListView) view.findViewById(R.id.countriesListView);
        countryListAdapter = new CountryListAdapter(getContext(), countryNamesModelList);
//        listView.setAdapter(countryListAdapter);

        fetchData();

        searchEditText.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) {

                countryListAdapter.getFilter().filter(charSequence);
                countryListAdapter.notifyDataSetChanged();
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }

        });

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

                Bundle position = new Bundle();
                position.putInt("position", i);
                Navigation.findNavController(view).navigate(R.id.action_affectedCountriesFragment_to_countryDetailsFragment, position);

            }
        });

        return view;
    }

    private void fetchData() {
        String Url = "https://corona.lmao.ninja/v2/countries/";
        RequestQueue requestQueue = Volley.newRequestQueue(getContext());
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
                Url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.i("hehes","entered");
                        try {
                            Log.i("hehe", response.toString());

                            for (int i = 0; i < response.length(); i++) {
                                JSONObject jsonObject = response.getJSONObject(i);
                                String countryName = jsonObject.getString("country");
                                String cases = jsonObject.getString("cases");
                                String todayCases = jsonObject.getString("todayCases");
                                String deaths = jsonObject.getString("deaths");
                                String recovered = jsonObject.getString("recovered");
                                String todayDeaths = jsonObject.getString("todayDeaths");
                                String active = jsonObject.getString("active");
                                String critical = jsonObject.getString("critical");

                                JSONObject object = jsonObject.getJSONObject("countryInfo");
                                String flagUrl = object.getString("flag");

                                countryNamesModel = new CountryNamesModel(getContext(),flagUrl, countryName, cases, todayCases, deaths, todayDeaths, recovered, active, critical);
                                countryNamesModelList.add(countryNamesModel);
                            }

                            countryListAdapter.notifyDataSetChanged();
                            listView.setAdapter(countryListAdapter);

                        }catch (Exception e) {
                            Log.i("error", e.getMessage());
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.i("errors", error.getMessage());
                        Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                }
        );

        requestQueue.add(jsonArrayRequest);
    }

My custom Adapter

package com.wordpress.myselfnikunj.cofighter.Adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.wordpress.myselfnikunj.cofighter.AffectedCountriesFragment;
import com.wordpress.myselfnikunj.cofighter.Model.CountryNamesModel;
import com.wordpress.myselfnikunj.cofighter.R;
import com.wordpress.myselfnikunj.cofighter.UpdatesFragment;

import java.util.ArrayList;
import java.util.List;

public class CountryListAdapter extends ArrayAdapter<CountryNamesModel> {

    private Context context;
    private List<CountryNamesModel> countryModelList;
    private List<CountryNamesModel> countryModelListFiltered;

    public CountryListAdapter( Context context, List<CountryNamesModel> countryModelList) {
        super(context, R.layout.countryitem, countryModelList);
        this.context = context;
        this.countryModelList = countryModelList;
        this.countryModelListFiltered = countryModelList;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.countryitem, null, true);
        TextView tvCountryName = view.findViewById(R.id.countryName);
        ImageView imageView = view.findViewById(R.id.countryImageFlag);

        tvCountryName.setText(countryModelListFiltered.get(position).getCountry());
        Glide.with(context).load(countryModelListFiltered.get(position).getFlag()).into(imageView);

        return view;
    }

    @Override
    public int getCount() {
        return countryModelListFiltered.size();
    }

    @Nullable
    @Override
    public CountryNamesModel getItem(int position) {
        return countryModelListFiltered.get(position);
    }

    @Override
    public long getItemId(int position)               {
        return position;
    }

    @NonNull
    @Override
    public Filter getFilter() {
         Filter filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults filterResults = new FilterResults();
                if (charSequence == null
                        || charSequence.length() == 0
                ) {
                    filterResults.count = countryModelList.size();
                    filterResults.values = countryModelList;
                } else {
                    List<CountryNamesModel> resultsModel = new ArrayList<>();
                    String searchStr = charSequence.toString().toLowerCase();

                    for (CountryNamesModel itemsModel: countryModelList) {
                        if(itemsModel.getCountry().toLowerCase().contains(searchStr)) {
                            resultsModel.add(itemsModel);
                        }
                        filterResults.count = resultsModel.size();
                        filterResults.values = resultsModel;
                    }
                }
                return  filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults results) {
                countryModelListFiltered = (List<CountryNamesModel>) results.values;
                UpdatesFragment.countryNamesModelList = (List<CountryNamesModel>) results.values;
                //AffectedCountriesFragment.countryNamesModelList = (List<CountryNamesModel>) results.values;
                notifyDataSetChanged();
            }
        };
        return filter;
    }
}

截图

Second Time

Third Time

当您导航到 AffectedCountriesFragment 的另一个片段视图被销毁并调用 public void onDestroyView() 时。当你 return 回来时 public View onCreateView 被再次调用。但是你的片段并没有完全被破坏,它的所有变量仍然存在并且处于它们离开时的状态。

这意味着当您导航到下一个片段时,您的 countryNamesModelList 会保持填充状态,而当您 return 返回 AffectedCountriesFragment 时,相同的填充列表会再次填充,从而导致条目重复.

你能做什么?

跟踪片段的状态。创建一个新的 class 级变量 private View view; 来保存片段的视图。

    // If null - must be initialized and returned in `onCreateView`
    // If not null - must be returned in `onCreateView` immediately
    // avoiding recreation of the same view (performance improvement)
    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (view == null) {
            // Inflate the layout for this fragment ONLY IF IT IS NULL
            View view = inflater.inflate(R.layout.fragment_affected_countries, container, false);

            searchEditText = (EditText) view.findViewById(R.id.searchEditText);
            listView = (ListView) view.findViewById(R.id.countriesListView);
            countryListAdapter = new CountryListAdapter(getContext(), countryNamesModelList);
    //        listView.setAdapter(countryListAdapter);

            fetchData();

            searchEditText.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) {

                    countryListAdapter.getFilter().filter(charSequence);
                    countryListAdapter.notifyDataSetChanged();
                }

                @Override
                public void afterTextChanged(Editable editable) {

                }

            });

            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

                    Bundle position = new Bundle();
                    position.putInt("position", I);
                    Navigation.findNavController(view).navigate(R.id.action_affectedCountriesFragment_to_countryDetailsFragment, position);

                }
            });
        }

        return view;
    }

确保您没有遗漏对 Activity 和 Fragment 生命周期的理解。 的生命周期。