Search code examples
androidfirebase-realtime-databaseandroid-recyclerviewfirebaseuiandroid-paging

Error: Can't call startAt() or equalTo() multiple times


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();
    }
}

Solution

  • 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.