Recyclerview这么慢,有很多物品 [英] Recyclerview is so slow with a lot of item

查看:66
本文介绍了Recyclerview这么慢,有很多物品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了这段代码,可以从5万个领域中检索并在recyclerview中显示它:

I have made this code that could retrieve from realm 50k items and show it in recyclerview:

public class ListAirportFragment
        extends Fragment {
    Realm realm;
    List<AirportR> airports = new ArrayList<>();
    RealmResults<AirportR> airps;
    RecyclerView recyclerView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_list_airport, container, false);

        RealmConfiguration defaultConfig = new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build();
        realm = Realm.getInstance(defaultConfig);

        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
        SearchView searchView = (SearchView) rootView.findViewById(R.id.searchview);

        final RealmResults<AirportR> airps = realm.where(AirportR.class).findAll();

        airports = realm.copyFromRealm(airps, 0);

        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        final AirportAdapter adapter = new AirportAdapter(airports, getActivity());
        recyclerView.setAdapter(adapter);

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

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

        return rootView;
    }

    private class AirportAdapter
            extends RecyclerView.Adapter<RecyclerView.ViewHolder>
            implements Filterable {
        private List<AirportR> originalAirports;
        private List<AirportR> listAirports;
        private Context context;
        private AirportFilter filter;
        private boolean isLoading;
        private int visibleThreshold = 5;
        private int lastVisibleItem, totalItemCount;
        private OnLoadMoreListener mOnLoadMoreListener;


        public AirportAdapter(List<AirportR> airports, Context context) {
            this.originalAirports = airports;
            this.listAirports = airports;
            this.context = context;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.airport_show, parent, false);
            AirportClass holder = new AirportClass(view);
            return holder;
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            AirportR airportR = listAirports.get(position);

            AirportClass mHolder = (AirportClass) holder;

            mHolder.country.setText(airportR.getIsoCountry());
            mHolder.name.setText(airportR.getName());
        }

        @Override
        public int getItemCount() {
            return listAirports.size();
        }

        @Override
        public Filter getFilter() {
            if(filter == null) {
                filter = new AirportFilter(this, originalAirports);
            }
            return filter;
        }

        private class AirportFilter
                extends Filter {
            private final AirportAdapter adapter;

            private final List<AirportR> originalList;

            private final List<AirportR> filteredList;

            private AirportFilter(AirportAdapter adapter, List<AirportR> originalList) {
                super();
                this.adapter = adapter;
                this.originalList = new LinkedList<>(originalList);
                this.filteredList = new ArrayList<>();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                filteredList.clear();
                final FilterResults results = new FilterResults();

                if(constraint.length() == 0) {
                    filteredList.addAll(originalList);
                } else {
                    final String filterPattern = constraint.toString().toLowerCase().trim();

                    for(final AirportR airportR : originalList) {
                        if(airportR.getName().contains(filterPattern)) {
                            filteredList.add(airportR);
                        }
                    }
                }
                results.values = filteredList;
                results.count = filteredList.size();
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                adapter.listAirports.clear();
                adapter.listAirports.addAll((ArrayList<AirportR>) results.values);
                adapter.notifyDataSetChanged();
            }
        }

        private class AirportClass
                extends RecyclerView.ViewHolder {
            TextView name, country;
            ImageView image;

            public AirportClass(View itemView) {
                super(itemView);
                name = (TextView) itemView.findViewById(R.id.name);
                country = (TextView) itemView.findViewById(R.id.country);
                image = (ImageView) itemView.findViewById(R.id.imageView);
            }
        }
    }
}

但是我有两个问题:

  1. 5万个物品的充电是如此缓慢(我按一下按钮进入片段后的30秒),所以我不知道如何快速充电:例如,可能只收取50个机场的时间费用?境界有可能吗?
  2. 过滤器无法正常工作,例如,如果我搜索Lowell,并且我输入lo却没有显示Lowell,为什么会出现此错误?
  1. the charging of the 50k items is so slow (30 seconds after I go to the fragment with a button) and so I don't know how to make it fast: it's possible to charge only 50 airports for time for example? It's possible it with realm?
  2. the filter is not working correctly, for example if I search Lowell and I digit lo it does not show Lowell, why this bug?

谢谢您的回答

推荐答案

我制作了这段代码,可以从5万个领域中检索并在recyclerview中显示它:

I have made this code that could retrieve from realm 50k items and show it in recyclerview:

final RealmResults<AirportR> airps = realm.where(AirportR.class).findAll(); airrports = realm.copyFromRealm(airps, 0);

final RealmResults<AirportR> airps = realm.where(AirportR.class).findAll(); airrports = realm.copyFromRealm(airps, 0);

那是因为您正在从UI线程上的零拷贝数据库中复制 50000个对象.

That's because you're copying 50000 objects from your zero-copy database on your UI thread.

解决方案:

1.)不要 复制零复制数据库

2.)在后台线程上将 50000个元素复制到内存中,并乐于使用内存

2.) copy out 50000 elements into memory on a background thread and have fun with the memory usage

老实说,很明显#2不是真正的解决方案,因此,您应该遵循如何使用Realm的惰性查询评估功能和托管对象的做法,而不是尝试通过调用realm.copyFromRealm()来对其进行破解

Honestly, it's quite obvious that #2 isn't a real solution, so instead, you should follow the practices of how to use Realm's lazy query evaluation feature and managed objects, rather than trying to hack it by calling realm.copyFromRealm()

这是解决方案#1 :

public class ListAirportFragment
        extends Fragment {
    Realm realm;
    RealmResults<AirportR> airps;
    RecyclerView recyclerView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_list_airport, container, false);

        RealmConfiguration defaultConfig = new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build();
        realm = Realm.getInstance(defaultConfig);

        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
        SearchView searchView = (SearchView) rootView.findViewById(R.id.searchview);

        airps = realm.where(AirportR.class).findAll();

        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        final AirportAdapter adapter = new AirportAdapter(realm, airps, getActivity());
        recyclerView.setAdapter(adapter);

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

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

        return rootView;
    }

    private class AirportAdapter
            extends RecyclerView.Adapter<RecyclerView.ViewHolder>
            implements Filterable {
        private RealmResults<AirPort> listAirports;
        private Context context;
        private Realm realm;

        private final RealmChangeListener realmChangeListener = new RealmChangeListener() {
            @Override
            public void onChange(Object element) {
                notifyDataSetChanged();
            }
        };

        public AirportAdapter(Realm realm, RealmResults<AirportR> airports, Context context) {
            this.realm = realm;
            this.listAirports = airports;
            this.listAirports.addChangeListener(realmChangeListener);
            this.context = context;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.airport_show, parent, false);
            AirportClass holder = new AirportClass(view);
            return holder;
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            AirportR airportR = listAirports.get(position);

            AirportClass mHolder = (AirportClass) holder;

            mHolder.country.setText(airportR.getIsoCountry());
            mHolder.name.setText(airportR.getName());
        }

        @Override
        public int getItemCount() {
            if(listAirports == null || !listAirports.isValid()) {
                return 0;
            }
            return listAirports.size();
        }

        @Override
        public Filter getFilter() {
            if(filter == null) {
                filter = new AirportFilter(this);
            }
            return filter;
        }

        private class AirportFilter
                extends Filter {
            private final AirportAdapter adapter;

            private AirportFilter(AirportAdapter adapter) {
                super();
                this.adapter = adapter;
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                final FilterResults results = new FilterResults();
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if(adapter.listAirports != null && adapter.listAirports.isValid()) {
                    adapter.listAirports.removeChangeListener(adapter.realmChangeListener);
                }
                if(constraint.length() == 0) {
                    adapter.listAirports = adapter.realm.where(AirportR.class).findAll();
                } else {
                    final String filterPattern = constraint.toString().toLowerCase().trim();
                    adapter.listAirports = adapter.realm.where(AirportR.class)
                                                .contains("fieldToQueryBy", filterPattern, Case.INSENSIIVE) // TODO: change field
                                                .findAll();
                }
                adapter.listAirports.addChangeListener(adapter.realmChangeListener);
                adapter.notifyDataSetChanged();
            }
        }

        private class AirportClass
                extends RecyclerView.ViewHolder {
            TextView name, country;
            ImageView image;

            public AirportClass(View itemView) {
                super(itemView);
                name = (TextView) itemView.findViewById(R.id.name);
                country = (TextView) itemView.findViewById(R.id.country);
                image = (ImageView) itemView.findViewById(R.id.imageView);
            }
        }
    }
}


此解决方案未使用RealmRecyclerViewAdapter并通过手动方式添加/删除了更改侦听器,但是您也可以使用RealmRecyclerViewAdapter以获得更好的效果寻找解决方案.


This solution didn't use RealmRecyclerViewAdapter and managed adding/removing change listener manually, but you can also use RealmRecyclerViewAdapter for a better looking solution.

这篇关于Recyclerview这么慢,有很多物品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆