Hello.

I use the official VK SDK and I want to get a list of VK users, starting with a specific id and ending with some number. In the documentation I did not find anything about the multiple values ​​of the parameters and decided to do it stupidly with a while . For example, get 20 users.

 do{ VKRequest request = VKApi.users().get(VKParameters.from(VKApiConst.FIELDS, "photo_50", VKApiConst.USER_ID, String.valueOf(id))); request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { super.onComplete(response); VKList<VKApiUserFull> vkList = (VKList<VKApiUserFull>) response.parsedModel; for (VKApiUserFull userFull : vkList) { ... //фильтрация значений. Если проходят проверку, то счетчик увеличивается. Если нет, то - break count++; } } }); id++; } while (count < 20); 

As mentioned above, this dumb cycle works. But there is a problem in that after its execution, for some reason, it begins anew. And it goes on endlessly. The loop itself is inside doInBackground AsyncTask method. In this case, after the end of the cycle, the onPostExecute method is onPostExecute . And then the cycle begins again. And from the same moment where he was stopped. Those. with indices 21, 22, 23, etc. I sat with the debager for more than an hour, but could not understand why he was going into an endless cycle. AsyncTask is AsyncTask by pressing Button 'a, so the call could not loop there.

If you describe everything briefly, then everything goes according to this scenario:

  1. Activity .
  2. AsyncTask by pressing a key.
  3. The loop passes the required number of times inside the doInBackground and terminates.
  4. Runs onPostExecute in AsyncTask .
  5. It takes a couple of seconds and the cycle starts again from the place where it was stopped.

Where is my slip?

UPD The fact that the counter is incremented within the request itself is not a random error. It increases only after the values ​​have passed the filter. This is exactly my gap: I need to somehow stop the cycle not after 20 passes through it, but after receiving 20 objects inside the onComplete request.

Get rid of the counter also fails: while (arrayList.size () <20) also leads to an infinite loop.

Thank you in advance for your response.

    1 answer 1

    You are not there to increase the value of the counter. You do this in the onComplete method, and it is called only after the successful execution of the request ... In general, it is not very clear what you wanted to get with this code. And what's the inner loop yet? ..

    You now have this procedure in the program:

    1. Go to do
    2. We start the request
    3. Increment id
    4. Go to the loop continuation condition and check that count less than 20
    5. Returning to point 1 until 20 requests are successfully executed.

    It will be executed successfully, but it will not start, because You increase the counter only after the end of the request, and not after its start. Yes, and in some kind of cycle ...

    You need something like this:

     do{ VKRequest request = VKApi.users().get(VKParameters.from(VKApiConst.FIELDS, "photo_50", VKApiConst.USER_ID, String.valueOf(id))); request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { super.onComplete(response); VKList<VKApiUserFull> vkList = (VKList<VKApiUserFull>) response.parsedModel; for (VKApiUserFull userFull : vkList) { ... //count++; } } }); count++; id++; } while (count < 20); 

    If you need to increment the counter exactly after the execution of the task, then the following tasks should be run only after the previous one has been completed. Those. something like this:

     int id = 0; public void foo(int count) { if (count>=20){return;} VKRequest request = VKApi.users().get(VKParameters.from(VKApiConst.FIELDS, "photo_50", VKApiConst.USER_ID, String.valueOf(id))); request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { super.onComplete(response); VKList<VKApiUserFull> vkList = (VKList<VKApiUserFull>) response.parsedModel; for (VKApiUserFull userFull : vkList) { ... //фильтрация значений. Если проходят проверку, то счетчик увеличивается. Если нет, то - break count++; } foo(count); } }); id++; } 
    • This, of course, is true, but I need to somehow increment the counter inside the query itself, because there I have (instead of ...) the filtering of the resulting values. Those. I need, not that the cycle passes 20 times, but so that 20 objects with the parameters I need are obtained. If you start the loop in the form in which you suggested, then the output will be an ArrayList of 1-2 objects (the rest have been filtered). And I need to get exactly 20 objects. If you do While before arrayList.size (), it also goes into an infinite loop. In general, this solution is not quite suitable for me. - ahgpoug
    • @ahgpoug, see the update response - try to run tasks recursively, starting the next only after the current one is executed. - Yuriy SPb
    • Looked at the answer. At a minimum, using the count variable is not possible here, because in this case it must be final. I decided to get rid of it by removing it from the method parameters and replacing the check with if (arrayList.size ()> = 20). The method, it seems, is executed, but does it not the necessary number of times. Those. the result is an arrayList of random size from 0 to 20. I don’t really understand why this happens, because the recursion does not even reach the point where it needs to be stopped. - ahgpoug
    • UPD: in general, this recursive method for some reason does not return more than 7-8. Put a condition on> = 100, but it returns all the same 4-8. - ahgpoug
    • @ahgpoug, maybe not all requests are successful with you, onComplete somewhere has not volunteered and nothing else will cause the method. You would need to add error handling - Yuriy Spb