我已经制作了这个代码,可以从领域50k项目中检索并在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
,为什么会出现此错误?感谢您的回答
答案 0 :(得分:3)
我已经制作了这个代码,可以从领域50k项目中检索并在recyclerview中显示它:
final RealmResults<AirportR> airps = realm.where(AirportR.class).findAll(); airrports = realm.copyFromRealm(airps, 0);
这是因为您在UI线程中从零拷贝数据库 复制 50000个对象。
解决方案:
1。)不 复制 零拷贝数据库中的元素
2。)在后台线程上将 50000个元素复制到内存中并享受内存使用的乐趣
老实说,很明显#2不是真正的解决方案,所以相反,你应该遵循如何使用Realm的懒惰查询评估功能和托管对象的做法,而不是试图通过调用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
并手动管理添加/删除更改侦听器,但您也可以use RealmRecyclerViewAdapter for a better looking solution.
答案 1 :(得分:1)
在列表中有这么多项目你真的认为有人实际上要滚动它吗?我的意思是,你确定这里需要一个项目列表,或者只是一个搜索栏更有效率吗?
如果你想保留你的设置,我建议3个改进:
不要一次加载所有可用数据。例如,向适配器添加50个对象,然后当您在RecyclerView上传递滚动位置30左右时,将接下来的50个结果添加到适配器。我在下面发布的代码片段的内容。 (听听滚动位置看这个问题:difference between EpicPandaForce的答案更好地解决了这个问题highestAvailable
and requireAdministrator
)
不要让搜索栏过滤填充的适配器。使用RealmResults自动更新数据库视图的事实,这样您就可以在其上实际执行新事务,以使用realm过滤数据而无需重新获取数据。 (请参阅领域How to implement endless list with RecyclerView?和docs)
这应该可以解决您的性能问题,您不必自己实现搜索,而是可以依赖Realms优化的性能。
1的代码段:仅留给记录。 EpicPandaForce的答案以更好的方式解决了这个问题
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
if (mGoogleApiClient.isConnected()) {
//Todo
}
}
答案 2 :(得分:0)
您应该从其他线程返回结果。如果你有50k ..主要线程要处理的很多。你应该使用50个元素的延迟加载。过滤搜索区分大小写。两个小写。