i want to show the result of a realm query in my recycler view, using a Filter.
So I've implemented this code:
public class ListAirportFragment extends Fragment
{
Realm realm;
List<AirportR>airports = new ArrayList<>();
#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 = (RecyclerView)rootView.findViewById(R.id.recyclerview);
SearchView searchView = (SearchView)rootView.findViewById(R.id.searchview);
recyclerView.setHasFixedSize(true);
//final RealmResults<AirportR> airps = realm.where(AirportR.class).findAllAsync();
final RealmResults<AirportR> airps = realm.where(AirportR.class).findAll();
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
final AirportAdapter adapter = new AirportAdapter(airports,getActivity());
recyclerView.setAdapter(adapter);
realm.executeTransaction(new Realm.Transaction()
{
#Override
public void execute(Realm realm)
{
for (int i = 0; i<airps.size();i++)
{
airports.add(airps.get(i));
adapter.notifyDataSetChanged();
}
}
});
/* airps.addChangeListener(new RealmChangeListener<RealmResults<AirportR>>() {
#Override
public void onChange(RealmResults<AirportR> element)
{
for (int i = 0; i<element.size();i++)
{
airports.add(element.get(i));
adapter.notifyDataSetChanged();
}
}
}); */
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;
}
}
and this is my adapter:
public class AirportAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable
{
private List<AirportR>originalAirports;
private List <AirportR>listAirports;
private Context context;
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 = originalAirports.get(position);
String country = airportR.getIsoCountry().toLowerCase()+".png";
int imgID = context.getResources().getIdentifier(country , "drawable", context.getPackageName());
AirportClass mHolder = (AirportClass)holder;
mHolder.image.setImageResource(imgID);
mHolder.country.setText(airportR.getIsoCountry());
mHolder.name.setText(airportR.getName());
}
#Override
public int getItemCount()
{
return listAirports.size();
}
#Override
public Filter getFilter()
{
return new Filter()
{
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
List<AirportR> filteredResults = null;
if (constraint.length() == 0)
{
filteredResults = originalAirports;
}
else
{
filteredResults = getFilteredResults(constraint.toString().toLowerCase());
}
Log.d("const",String.valueOf(constraint.length()));
FilterResults results = new FilterResults();
results.values = filteredResults;
return results;
}
protected List<AirportR> getFilteredResults(String constraint)
{
List<AirportR> results = new ArrayList<>();
for (AirportR item : originalAirports)
{
if (item.getName().toLowerCase().contains(constraint))
{
results.add(item);
}
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
listAirports = (List<AirportR>)results.values;
AirportAdapter.this.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);
}
}
}
the problem is: when I try to put something to searchView it crashes and, with the debugger, I see this error message:
W/Filter: An exception occured during performFiltering()!
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
What's the problem? Before I've user findAllAsync() method to get the result and after I use simple findAll() but I get the same error message...does it not the same thread? Or there are other problems in the filter?
Thanks
The problem is that you query for airports on the UI thread, and later tries to access these same objects in another thread. This is not allowed.
The method performFiltering runs on a worker thread. When it calls getFilteredResults, it tries to access a property(item.getName()) of a Realm Object that was queried on another thread(UI). As the error says, Realm objects can only be accessed on the thread they were created.
If you want to be able to access the objects you queried for in another thread, you might want to get a deep copy of them, so that they are detached from Realm. In your example, after querying for airports, you could use the method copyFromRealm() to get a list of regular Airport objects and use it from thereon.
Related
I'm having trouble updating a RecyclerView with SearchView results in a Fragment.
Doing the actual search seems to work fine as I've stepped through the code at "performFiltering" and the "publishResults" has the correct list. But I can't seem to figure out how to update the RecyclerView. I've been staring at this code for 3 days now and is likely a simple solution I'm overlooking.
MyMoviesFragment
public class MyMoviesFragment extends Fragment {
private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;
private static final boolean DEFAULT_SORT_ORDER_IS_ASC = false;
private static final int MY_MOVIES_LOADER_ID = 173201;
private ArrayList<Movie> _movies = new ArrayList();
private ArrayList<Movie> _moviesRaw = new ArrayList();
private Button _btnMoviesNotFound;
private DBHandler _repository;
private MyMoviesAdapter _myMoviesAdapter;
private ProgressBar _progressBar;
private RecyclerView _rvMovies;
private SharedPreferences _preferences;
private View _view;
public MyMoviesFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
_myMoviesAdapter.getFilter().filter(newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
Log.i("onQueryTextSubmit", query);
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
}
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
this._view = inflater.inflate(R.layout.fragment_my_movies, container, DEFAULT_SORT_ORDER_IS_ASC);
getActivity().setTitle(R.string.movies_fragment_title);
this._repository = DBHandler.getInstance(getActivity());
this._progressBar = (ProgressBar) this._view.findViewById(R.id.progressBar2);
this._progressBar.setVisibility(View.VISIBLE);
this._rvMovies = (RecyclerView) this._view.findViewById(R.id.rvMovies);
this._rvMovies.setLayoutManager(new LinearLayoutManager(getActivity()));
this._myMoviesAdapter = new MyMoviesAdapter(this._movies, this);
this._rvMovies.setAdapter(this._myMoviesAdapter);
this._btnMoviesNotFound = (Button) this._view.findViewById(R.id.btnMoviesNotFound);
if (savedInstanceState == null) {
loadMyMoviesList();
}
return this._view;
}
public void loadMyMoviesList() {
getLoaderManager().initLoader(MY_MOVIES_LOADER_ID, null, new LoaderManager.LoaderCallbacks<ArrayList<Movie>>() {
#NonNull
#Override
public Loader<ArrayList<Movie>> onCreateLoader(int id, Bundle args) {
return new MyMoviesLoader(MyMoviesFragment.this.getContext());
}
public void onLoadFinished(Loader<ArrayList<Movie>> loader, ArrayList<Movie> movies) {
if (movies != null) {
MyMoviesFragment.this._movies.clear();
Iterator it = movies.iterator();
while (it.hasNext()) {
MyMoviesFragment.this._movies.add((Movie) it.next());
}
MyMoviesFragment.this._moviesRaw = new ArrayList(MyMoviesFragment.this._movies);
MyMoviesFragment.this._myMoviesAdapter.notifyDataSetChanged();
MyMoviesFragment.this.displayListState();
}
}
public void onLoaderReset(Loader<ArrayList<Movie>> loader) {
}
}).forceLoad();
}
public void displayListState() {
this._progressBar.setVisibility(View.GONE);
if (this._movies.size() < 1) {
this._rvMovies.setVisibility(View.GONE);
this._btnMoviesNotFound.setVisibility(View.VISIBLE);
return;
}
this._btnMoviesNotFound.setVisibility(View.GONE);
this._rvMovies.setVisibility(View.VISIBLE);
}
}
MyMoviesAdapter
public class MyMoviesAdapter extends RecyclerView.Adapter<MyMoviesAdapter.ViewHolder> implements Filterable {
private Activity _activity;
private ArrayList<Movie> _movieListFull;
private ArrayList<Movie> _movieListFiltered;
private DBHandler _repository = DBHandler.getInstance(this._activity);
private Fragment _fragment;
public MyMoviesAdapter(ArrayList<Movie> movies, Fragment fragment) {
this._activity = fragment.getActivity();
this._fragment = fragment;
this._movieListFull = movies;
}
protected class ViewHolder extends RecyclerView.ViewHolder {
private CardView cardMovie;
private TextView lblMovieTitle;
public ViewHolder(View itemView) {
super(itemView);
this.cardMovie = (CardView) itemView.findViewById(R.id.cardMovie);
this.lblMovieTitle = (TextView) itemView.findViewById(R.id.lblMovieTitle);
}
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie, parent, false));
}
// Replace the contents of a view (invoked by the layout manager)
// Binds the data to the Views in each row
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// Get the data model based on position
Movie movie = _movieListFull.get(position);
viewHolder.lblMovieTitle.setText(String.valueOf(movie.getTitle()));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this._movieListFull.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
_movieListFiltered = _movieListFull;
} else {
ArrayList<Movie> filteredList = new ArrayList<>();
for (Movie movie : _movieListFull) {
if (movie.getTitle().toLowerCase().contains(charString)) {
filteredList.add(movie);
}
}
_movieListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = _movieListFiltered;
filterResults.count = _movieListFiltered.size();
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
_movieListFiltered = (ArrayList<Movie>) filterResults.values;
notifyDataSetChanged();
}
};
}
}
If _movieListFull is full data set, then _movieListFiltered should be used for display. Therefore getItemCount() and onBindViewHolder() should refer to _movieListFiltered.
Try the following changes:
public MyMoviesAdapter(ArrayList<Movie> movies, Fragment fragment) {
this._activity = fragment.getActivity();
this._fragment = fragment;
this._movieListFiltered = movies;
_movieListFull = new ArrayList<>();
_movieListFull.addAll(movies);
}
// Replace the contents of a view (invoked by the layout manager)
// Binds the data to the Views in each row
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// Get the data model based on position
Movie movie = _movieListFiltered.get(position);
viewHolder.lblMovieTitle.setText(String.valueOf(movie.getTitle()));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this._movieListFiltered.size();
}
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
//_movieListFiltered = _movieListFull;
_movieListFiltered.addAll(_movieListFull);
} else {
ArrayList<Movie> filteredList = new ArrayList<>();
for (Movie movie : _movieListFull) {
if (movie.getTitle().toLowerCase().contains(charString)) {
filteredList.add(movie);
}
}
_movieListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = _movieListFiltered;
filterResults.count = _movieListFiltered.size();
return filterResults;
}
Hope that helps!
I have a RecyclerView thats populated from my Firebase Database. The list is quite long so I want the user to be able to search the list. But when the user types the first character into the SearchView, nothing at all is returned.
This is the onCreateView in my FavouriteFragment UPDATED
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_favourites, container, false);
mAuth = FirebaseAuth.getInstance();
current_user_id = mAuth.getCurrentUser().getUid();
recyclerView = (RecyclerView) view.findViewById(R.id.route_favourites);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
search = (SearchView) view.findViewById(R.id.search);
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("BusRoute");
rootRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot datasnapshot : dataSnapshot.getChildren()){
String key = datasnapshot.getKey();
Query query = rootRef.child(key).orderByChild("route").equalTo(newText);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
favouritesAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return true;
}
});
favouritesAdapter = new FavouritesAdapter(getDataSetHistory(), getActivity());
favouritesAdapter.notifyDataSetChanged();
recyclerView.setAdapter(favouritesAdapter);
getBusRoutes();
return view;
}
This is my favouritesAdapter:
public class FavouritesAdapter extends RecyclerView.Adapter<FavouritesAdapter.ViewHolder> implements Filterable {
private List<BusRoute> favourites;
private List<BusRoute> searchList;
private Context context;
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView routeTextView, originTextView, destinationTextView;
ImageView addFavouritesButton;
ViewHolder(View v){
super(v);
this.routeTextView = v.findViewById(R.id.route);
this.destinationTextView = v.findViewById(R.id.destination);
this.originTextView = v.findViewById(R.id.origin);
this.addFavouritesButton = v.findViewById(R.id.addToFavourites);
addFavouritesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String route = routeTextView.getText().toString();
System.out.println("clicked");
System.out.println(route);
//addToFavourites(route);
}
});
}
#NonNull
#Override
public FavouritesAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.favourite_card, parent, false);
return new FavouritesAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull FavouritesAdapter.ViewHolder viewHolder, int i) {
BusRoute bus = favourites.get(i);
viewHolder.originTextView.setText(String.valueOf(bus.getOrigin()));
viewHolder.destinationTextView.setText(String.valueOf(bus.getDestination()));
viewHolder.routeTextView.setText(String.valueOf(bus.getRoute()));
}
public FavouritesAdapter(ArrayList<BusRoute> favourites, Context context){
this.context = context;
this.favourites = favourites;
searchList = new ArrayList<>(favourites);
}
#Override
public int getItemCount() {
System.out.println(favourites);
return favourites.size();
}
#Override
public Filter getFilter() {
return favouriteFilter;
}
private Filter favouriteFilter = new Filter(){
#Override
protected FilterResults performFiltering(CharSequence constraint) {
System.out.println("filter results");
List<BusRoute> filteredList = new ArrayList<>();
if(constraint==null || constraint.length()==0){
filteredList.addAll(searchList);
}else{
String filterPattern = constraint.toString().toLowerCase().trim();
for(BusRoute br : searchList){
if(br.getRoute().toLowerCase().contains(filterPattern)){
filteredList.add(br);
}else{
System.out.println("nothing here");
}
}
}
System.out.println("set filter results");
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
favourites.clear();
favourites.addAll((List)results.values);
notifyDataSetChanged();
}
};
}
I just want to have a filterable search bar but cannot get it working! I'd appreciate any help at all!
In publish results method. Don't clear your array list. That is the reason for empty data
Try this
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String query = charSequence.toString();
List<String> filtered = new ArrayList<>();
if (query.isEmpty()) {
filtered = items;
} else {
for (String movie : items) {
if (movie.toLowerCase().contains(query.toLowerCase())) {
filtered.add(movie);
}
}
}
FilterResults results = new FilterResults();
results.count = filtered.size();
results.values = filtered;
return results;
}
I am working on an android app where I am going to store school names under one node for e.g. schools. I want to implement Autocomplete functionality for the schoolnames, .i.e when user starts typing school name he/she will see the schoolnames starting/matching the particular condition(top 5 records matching the condition can be shown). Assume that each schoolname is a String.
public class SchoolsAutoCompleteAdapter extends BaseAdapter implements Filterable {
private static final int MAX_RESULTS = 10;
private Context mContext;
FirebaseDatabase database;
DatabaseReference myRef;
private List<School> schools = new ArrayList<School>();
public SchoolsAutoCompleteAdapter(Context mContext) {
this.mContext = mContext;
database=FirebaseDatabase.getInstance();
myRef=database.getReference("mschools");
schools=new ArrayList<>();
}
#Override
public int getCount() {
return schools.size();
}
#Override
public School getItem(int position) {
return schools.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.school_autocomplete_list_row, parent, false);
}
((TextView) convertView.findViewById(R.id.autocomplete_email)).setText(getItem(position).getEmail());
((TextView) convertView.findViewById(R.id.autocomplete_name)).setText(getItem(position).getName());
return convertView;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
schools = findSchools(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = schools;
filterResults.count = schools.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}};
return filter;
}
private List<School> findSchools(String studentUsername) {
final List<School> schools=new ArrayList<>();
Query abc= myRef.orderByChild("schoolname").startAt(studentUsername).endAt(studentUsername+"\uf8ff").limitToFirst(5);
abc.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
//schools.add(childDataSnapshot.getValue(School.class));
School s=childDataSnapshot.getValue(School.class);
schools.add(new School(s.getEmail(),s.getName()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return schools;
}
}
As per the code return schools line is executing before the onDataChange method as firebase executes asynchronously .So it is returning empty record.
Some relational database can be used to implement this functionality, but I don't want to add extra database to implement just this functionality. If I keep breakpoint at return schools; line, I am able to see the result. Can I implement this scenario using Firebase or am I missing something?
I am able to filter listview using searchview which is working fine. My listview is updating every seconds for this handler is used to update the adapter.
private void nonstoprun() {
handler = new Handler();
update = new Runnable() {
#Override
public void run() {
musers = (ArrayList<mobstat>) mobstat.listAll(mobstat.class);
descAdapter = new DescAdapter(seconds.this, musers, seconds.this);
contlist.setAdapter(descAdapter);// Notify our update
handler.postDelayed(this , 1000);
// android.widget.Filter filter = descAdapter.getFilter();
//filter.filter(searchView.getQuery());
}
};
handler.postDelayed(update, 10);
}
So, After i type the string in the searchview the listview is filtered but immediately it shows the complete listview as it is not maintain the filtered values.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.search));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
android.widget.Filter filter = descAdapter.getFilter();
filter.filter(newText);
return true;
}
});
//searchView.setSubmitButtonEnabled(true);
return true;
}
Myadapter:
public class DescAdapter extends BaseAdapter implements Filterable {
private seconds ds;
private ArrayList<mobstat> musers;
private ArrayList<mobstat> mOrig;
Activity seconds;
public DescAdapter(seconds ds, ArrayList<mobstat> musers, Activity seconds) {
this.ds = ds;
this.musers = musers;
this.seconds = seconds;
}
#Override
public int getCount() {
return musers.size();
}
#Override
public Object getItem(int i) {
return musers.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
mobstat du = musers.get(i);
String name = du.name;
String status = du.status;
Viewholder viewholder;
if(view==null) {
viewholder = new Viewholder();
view = LayoutInflater.from(ds).inflate(R.layout.custom, null);
viewholder.uname = (TextView) view.findViewById(R.id.name);
viewholder.ustatus = (TextView) view.findViewById(R.id.status);
view.setTag(viewholder);
} else { viewholder = (Viewholder) view.getTag(); }
viewholder.uname.setText(name);
viewholder.ustatus.setText(status);
return view;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final ArrayList<mobstat> results = new ArrayList<mobstat>();
if (mOrig == null)
mOrig=musers;
if(constraint!=null){
if(mOrig!=null && mOrig.size()>0){
for(final mobstat g : mOrig){
if (g.getname().toLowerCase().contains(constraint.toString())){
results.add(g);}
}
}
oReturn.values=results;
}
return oReturn;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
musers= (ArrayList<mobstat>) results.values;
notifyDataSetChanged();
}
};
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
Why filtered list is not maintaining even-though adapter values are updating every seconds.
I see the need of updating values from server. You can write a new constructor for the adapter passing as parameter the query string(if it is not empty maybe).
Filter the values in the constructor should work.
If you filter values after the constructor you will probably get a glitch in the UI as the adapter is first initialized with all values and then filtered
I have a DB named RealmItem and I have all users have territories they are attached to. Which is n size unknown. Every item has a field called territory. Now, is there a way to query Realm to find all Item Records that has any of the territoryID attached to the user. The reason I'm in need of this is because, I pipe a AutoCompleteTextView to a filtering adapter that looks like this:
public class ItemFilterAdapter extends BaseAdapter implements Filterable {
private static final String TAG = ItemFilterAdapter.class.getSimpleName();
private Context mContext;
private List<RealmItem> mResult = new ArrayList<>();
private LayoutInflater inflater;
private boolean needsFilter = false;
public ItemFilterAdapter(Context mContext) {
this.mContext = mContext;
}
public void setNeedsFilter(boolean needsFilter) {
this.needsFilter = needsFilter;
}
#Override
public int getCount() {
return mResult.size();
}
#Override
public Object getItem(int position) {
return mResult.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (view == null)
view = inflater.inflate(R.layout.item_update_autocomplete, parent, false);
RealmItem item = mResult.get(position);
TextView updateName = (TextView) view.findViewById(R.id.update_name);
TextView updateAddress = (TextView) view.findViewById(R.id.update_address);
if (item != null) {
updateName.setText(item.getName());
try {
JSONObject obj = new JSONObject(item.getPayload());
String address = obj.getString("address");
updateAddress.setText(address);
} catch (Exception e) {
e.printStackTrace();
}
}
return view;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
return null;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
if (constraint != null) {
mResult = filterDealers(constraint.toString());
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}
#NonNull
private List<RealmItem> filterDealers(String query) {
Realm mRealm = RealmUtils.getRealmInstance(mContext);
if (!needsFilter) {
return mRealm.where(RealmItem.class)
.contains("name", query, Case.INSENSITIVE)
.equalTo("id", [array of Ids]) <-- This is where I need it
.findAll();
} else {
return mRealm.where(RealmItem.class)
.contains("name", query, Case.INSENSITIVE)
.notEqualTo("activeStatus", "inactive")
.equalTo("id", [array of Ids]) <-- This is where I need it
.findAll();
}
}
}
More like looking for something like this .equalTo("id", [array of Ids]) <-- This is where I need it or anything nice to make filtering seemlessly smooth 😉
Aren't you basically just looking for the in() operator, added in 1.1.0?
public RealmQuery<E> in(
String fieldName, Integer[] values)