BackendlessDataQuery setPageSize()

The BackendlessDataQuery allows me to setPageSize() up to 100. What if I have about 350 rows to return in the find(), do i have to call the find() 4 times or how do I iterate through all pages?

Thanks

do i have to call the find() 4 times

Yes.

how do I iterate through all pages?
See the example here:
https://backendless.com/feature-17-data-paging-or-how-to-efficiently-load-large-data-sets-in-a-mobile-app/

Thank you Mark. I’ll try it out.

It executed if(size >0) 3 times with the sample code; however, it did not work if a remove() is called inside if (size > 0):

if( size > 0 )
{
offset+=restaurants.getCurrentPage().size();
restaurants.getPage(100, offset, new AsyncCallback<BackendlessCollection<Restaurant>>() {
@Override
public void handleResponse(BackendlessCollection<Restaurant> restaurants) {
for (Restaurant restaurant : restaurants.getData())
{
Backendless.Persistence.of(Restaurant.class).remove(restaurant , new AsyncCallback<Long>() {
@Override
public void handleResponse(Long aLong) {
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
}
});
}
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
}
});
}
else
{
latch.countDown();
}

I meant it executed only one time to remove first 100 rows.

Sorry, I didn’t understand what exactly didn’t work.

If there are 350 rows and without calling the remove(), the above code from the link will execute the 4 times each will return 100, 100,100,50 rows. However, if we call the remove() inside, the code only execute once with 100 rows. Sorry if I can’t explain that well. Don’t worry, I’ll try different approach.
Thanks.

When you call remove, the underlying offset value will be changing. Does your code account for that? The code from the article will not work “as is”, it will need to be modified. You will need to use the getPage method which takes the “offset” argument:
https://github.com/Backendless/Android-SDK/blob/master/src/com/backendless/BackendlessCollection.java#L71

Regards,
Mark

Since first 100 rows got remove, I thought the offset should be 0 again but it did not work either. For short, what I’m trying to learn is how to remove all the rows from the table using Asynchronous API.

You do not need to use paging for that, here’s a pseudo algorithm:

    Set max page size (100) Load all records with that page size (without any paging, just the first page of data) If the collection size is zero, go to step 6 iterate over the received collection and delete each object on the backend goto 1 You're done.

Thank you Mark. I had tried something like this before but the trick is this is Asynchronous calls, it won’t execute 3 and 4 as you wish, I keeps calling 1, 2 and 5. And nothing got removed in DB. When I found paging, i thought that can do so that I don’t have to call find() many times. I’ll try to play with it a bit more and will let you know.

I am curious, what is the use-case for deleting all records from the app running on a device?

It’s just to clean up no longer value data. Below is some code that I had tried before that it will never remove records in db.

first = true;
total = 0;
dataQuery.setPageSize(100)

while (first || total > 0)
{
Backendless.Persistence.of(Restaurant.class).find(dataQuery, new AsyncCallback<BackendlessCollection<Restaurant>>()
{
@Override
public void handleResponse(BackendlessCollection<Restaurant> restaurants
{
if(first)
{
total = restaurants.getTotalObjects();
first = false;
}
for(Restautant restaurant : restaurants.getData())
{
Backendless.Persistence.of(Restaurant.class).remove(restaurant, new AsyncCallback<Long>() {
@Override
public void handleResponse(Long aLong) {
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
textView.setText(“Failed to delete!”);
}
});
}
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
textView.setText(“Failed to Find”);
}
});
total -= 100;
}

I do not see how that code would even compile - you’re accessing “first” and “total” variables in the inner class. I assume they would need to be declared “final” in order to be visible, but if they are final, they cannot be changed.

Btw, there is no reason to have neither “first” nor the “total” variables to get this done.

Those are private variables in class module. That way you can set their values without compile errors. I decided to invoke Event clicked few times until the total count showing 0. And it worked now.

I’m new and still learning a lot about multi-threading and Backendless. Thank you so much for your patient and your support. I truly appreciate!

Here’s my solution for the problem. Btw, it would be simpler to remove all objects using backendless console ))

public class RemoveAll
{
  boolean done = false;
  Semaphore mutex = new Semaphore( 1 );
  int objectsToDelete;


  AsyncCallback&lt;Long&gt; removeCallback = new AsyncCallback&lt;Long&gt;()
  {
    @Override
    public void handleResponse( Long response )
    {
      checkAndReleaseMutex();
    }


    @Override
    public void handleFault( BackendlessFault fault )
    {
      checkAndReleaseMutex();
    }
  };


  AsyncCallback&lt;BackendlessCollection&lt;Restaurant&gt;> findCallback = new AsyncCallback&lt;BackendlessCollection&lt;Restaurant&gt;>()
  {
    @Override
    public void handleResponse( BackendlessCollection&lt;Restaurant&gt; response )
    {
      try
      {
        objectsToDelete = response.getCurrentPage().size();


        if( objectsToDelete == 0 )
        {
          done = true;
          mutex.release();
        }


        for( Restaurant restaurant : response.getCurrentPage() )
          Backendless.Persistence.of( Restaurant.class ).remove( restaurant, removeCallback );
      }
      catch( Exception e )
      {


      }
    }


    @Override
    public void handleFault( BackendlessFault fault )
    {
       System.out.println( fault.toString() );
    }
  };


  private void checkAndReleaseMutex()
  {
    objectsToDelete--;


    if( objectsToDelete == 0 )
      mutex.release();
  }


  public void removeAll() throws Exception
  {
    BackendlessDataQuery dataQuery = new BackendlessDataQuery();
    dataQuery.setPageSize( 10 );


    while( !done )
    {
      mutex.acquire();


      if( done )
      {
        mutex.release();
        break;
      }


      Backendless.Persistence.of( Restaurant.class ).find( dataQuery, findCallback );
    }
  }
}

I had used console before but when i got up to 3, 4 hundreds, thought it would be nice if I can program it with one click. I’ll try the code out soon.

Thanks Mark.

Mark,

The solution above did not execute the findCallback and the removeCallback. The second time it executed the while loop, it stopped at mutex.acquire(). I looked at the Threads and saw that the “Signal Catcher” is on WAIT forever.

Why do you need to execute the while loop twice?

I’m not sure what you meant but the loop executed again because “done” is still false. I saw it stopped at the 2nd time when it called mutex.acquire()