I want to find and list the text that the user wrote with EditText in the Firebase database.
Since I will use a lot of data in my application, I list them by paging. I'm using a library to list.
That's my problem. When I want to restrict the data I'm looking for with query to startAt ()
and endAt ()
, the application crashes and gives this error.
"Can't call startAt() or equalTo() multiple times"
When I remove startAt ()
and endAt ()
from the Query, there is no problem, but all the data is listed instead of the user-requested data. I think the query startAt()
and endAt()
don't work with the library I use. But I have to use it. With this library, I can query the Firebase database of the text the user has written with EditText.
Note: The application fails but finds and lists the data the user is looking for before making an error.
Sorry for my bad English.
My build.gradle:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.firebaseui:firebase-ui-database:4.3.2'
implementation 'com.google.firebase:firebase-database:19.0.0'
implementation 'com.google.android.gms:play-services-ads:18.1.1'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.nightonke:boommenu:2.1.1'
implementation "com.andkulikov:transitionseverywhere:1.7.9"
implementation "android.arch.paging:runtime:1.0.1" //For Paging Runtime
implementation 'com.shreyaspatil:FirebaseRecyclerPagination:1.0.1' //For Firebase Recycler Paging
testİmplementation 'junit:junit:4.12'
androidTestİmplementation 'com.android.support.test:runner:1.0.2'
androidTestİmplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
My User.java:
public class User {
public String name;
public String phone;
public User() {
}
public User(String name, String phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
My NameViewHolder:
public class NameViewHolder extends RecyclerView.ViewHolder {
public TextView result_name;
public NameViewHolder(View itemView) {
super(itemView);
result_name = (TextView)itemView.findViewById(R.id.Search_Result_Name);
}
}
My Activity:
public class MainActivity extends AppCompatActivity {
EditText Search_Edit_Text;
Button Search_Button;
Query firebaseSearchQuery;
DatabaseReference mUserDatabase;
private SwipeRefreshLayout mSwipeRefreshLayout;
FirebaseRecyclerPagingAdapter<User, NameViewHolder> mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Contacts");
mSwipeRefreshLayout = findViewById(R.id.swipe_refresh_layout);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mAdapter.refresh();
}
});
Search_Edit_Text = (EditText) findViewById(R.id.Search_Edit_Text);
Search_Button = (Button) findViewById(R.id.Search_Button);
Search_Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String searchText = Search_Edit_Text.getText().toString().trim();
firebaseUserSearchTest(searchText);
}
}
private void firebaseUserSearchTest(String searchText) {
Query myQuery = mUserDatabase.orderByChild("phone")
.startAt(searchText).endAt(searchText + "\uf8ff"); //It works fine when I remove it, but the user doesn't have any data.
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(5)
.setPageSize(10)
.build();
DatabasePagingOptions<User> optionss = new DatabasePagingOptions.Builder<User>()
.setLifecycleOwner(this)
.setQuery(myQuery, config, User.class)
.build();
mAdapter = new FirebaseRecyclerPagingAdapter<User, NameViewHolder>(optionss) {
@NonNull
@Override
public NameViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new NameViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false));
}
@Override
protected void onBindViewHolder(@NonNull NameViewHolder holder, int position, @NonNull User model) {
holder.result_name.setText(model.getName());
}
@Override
protected void onLoadingStateChanged(@NonNull LoadingState state) {
switch (state) {
case LOADING_INITIAL:
case LOADING_MORE:
// Do your loading animation
mSwipeRefreshLayout.setRefreshing(true);
break;
case LOADED:
// Stop Animation
mSwipeRefreshLayout.setRefreshing(false);
break;
case FINISHED:
//Reached end of Data set
mSwipeRefreshLayout.setRefreshing(false);
break;
case ERROR:
retry();
break;
}
}
};
Search_Contact_List.setAdapter(mAdapter);
}
@Override
protected void onStart() {
super.onStart();
if (adapter !=null)
adapter.startListening();
}
@Override
protected void onResume() {
super.onResume();
if (adapter !=null)
adapter.startListening();
ShowInterstitial();
}
@Override
protected void onStop() {
if (adapter !=null)
adapter.stopListening();
super.onStop();
}
}
The FirebaseUI FirebaseRecyclerPagingAdapter
uses Firebase Realtime Database queries to paginate the data. For this reason it must be used with a DatabaseReference
or a Query
without limits, and can't be combined with your own query/limits.
Firebase Database queries can only order/filter on a single property. In many cases it is possible to combine the values you want to filter on into a single (synthetic) property. For an example of this and other approaches, see my answer here: http://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase. But if you go this route, it's likely that you'll have to implement your own adapter on the data structure.