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);
}
}
}
}
Lowell
lo
Lowell
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);
That's because you're copying 50000 objects from your zero-copy database on your UI thread.
Solutions:
1.) don't copy the elements out from the zero-copy database
2.) copy out 50000 elements into memory on a background thread and have fun with the memory usage
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()
So this is solution #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);
}
}
}
}
This solution didn't use RealmRecyclerViewAdapter
and managed adding/removing change listener manually, but you can also use RealmRecyclerViewAdapter for a better looking solution.