1

I'm using Vk Sdk. I have created AsyncTask to load data from the server in background. However, it turns out that doInBackground() is finished before the tasks inside of it are done. The code is below:

@Override
protected Void doInBackground(Void... params) {
    Log.v(TAG, "Before Loading in Background");

    VKRequest request = VKApi.wall().get(VKParameters.from(VKApiConst.OWNER_ID, "-100177655", VKApiConst.OFFSET, "2"));
    request.executeWithListener(new VKRequest.VKRequestListener() {
        @Override
        public void onComplete(VKResponse response) {
            super.onComplete(response);

            String jsonData = response.responseString;
            Log.v(TAG, "json is ready");
            try {
                Log.v(TAG, "before parsing");
                parsePostsData(jsonData);
                Log.v(TAG, "after parsing");
            } catch (JSONException e) {
                Log.v(TAG, "EXCEPTION is thrown");
                e.printStackTrace();
            }
        }
    });

    Log.v(TAG, "Finished Background Tasks");
    return null;
}

I suspect that request.executeWithListener(...) is creating another thread and doing necessary work there. Therefore, AsyncTask thinks that work in his thread is finished. However, I'm not sure. There is nothing in the documentation for this method.

Another question is on which thread onComplete(...) method is running when it is called? On main or the same separate thread created by request?

Any help is appreciated :)

Marat
  • 6,142
  • 6
  • 39
  • 67
  • 1
    You are right. The callback/Listener is the culprit. You don't need the `AsyncTask` if the request is asynchronous – Elvis Chweya Aug 25 '16 at 10:56
  • I assume that it works similar to okHttp's `Call` execute with an async callback – Elvis Chweya Aug 25 '16 at 10:58
  • @ElvisChweya What do you think about `onComplete(...)` method? Is it running on main thread? How to check that? – Marat Aug 25 '16 at 11:23
  • From the source code here https://github.com/VKCOM/vk-android-sdk/blob/master/vksdk_library/src/main/java/com/vk/sdk/api/VKRequest.java, I gather `onComplete` is called from the Thread is was created...So, on the MainThread if the request was from the MainThread. I don't have much experience with vk-sdk for android, that being said. – Elvis Chweya Aug 25 '16 at 11:38

2 Answers2

1

Base on your code, you have 2 different Threads called. AsynTask is a background thread which will execute first. Then you called VKRequest executeWithListener which will created another thread in doInBackground().

To archive this in single Thread, you should change your execute method to executeSyncWithListener() in VKRequest

@Override
protected Void doInBackground(Void... params) {
    Log.v(TAG, "Before Loading in Background");

    VKRequest request = VKApi.wall().get(VKParameters.from(VKApiConst.OWNER_ID, "-100177655", VKApiConst.OFFSET, "2"));
    request.executeSyncWithListener(new VKRequest.VKRequestListener() {
        @Override
        public void onComplete(VKResponse response) {
            super.onComplete(response);

            String jsonData = response.responseString;
            Log.v(TAG, "json is ready");
            try {
                Log.v(TAG, "before parsing");
                parsePostsData(jsonData);
                Log.v(TAG, "after parsing");
            } catch (JSONException e) {
                Log.v(TAG, "EXCEPTION is thrown");
                e.printStackTrace();
            }
        }
    });

    Log.v(TAG, "Finished Background Tasks");
    return null;
}

Hope this will help!

THANN Phearum
  • 1,969
  • 22
  • 19
0

Do something like this:

@Override
protected Void doInBackground(Void... params) {
    Log.v(TAG, "Before Loading in Background");

    VKRequest request = VKApi.wall().get(VKParameters.from(VKApiConst.OWNER_ID, "-100177655", VKApiConst.OFFSET, "2"));
    request.executeWithListener(new VKRequest.VKRequestListener() {
        @Override
        public void onComplete(VKResponse response) {
            super.onComplete(response);

            String jsonData = response.responseString;
            Log.v(TAG, "json is ready");

// YOUR CUSTOM CALLBACK
new Thread(new myCustomRunnable(jsonData)).start();
            try {
                Log.v(TAG, "before parsing");
                parsePostsData(jsonData);
                Log.v(TAG, "after parsing");
            } catch (JSONException e) {
                Log.v(TAG, "EXCEPTION is thrown");
                e.printStackTrace();
            }
        }
    });

    Log.v(TAG, "Finished Background Tasks");
    return null;
}

where myCustomRunnable is a class that implements 'Runnable' interface.

public class myCustomRunnable implements Runnable{
    private String msg ="";
    public OToast(String msg) {
        this.msg = msg;
    }
    @Override
    public void run() {
//here do anything you want 
Log.v("mylog",msg);
//or even execute code in main thread:
runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //your code
                }
            });
    }

}

Or even simpler:

 @Override
    protected Void doInBackground(Void... params) {
        Log.v(TAG, "Before Loading in Background");

        VKRequest request = VKApi.wall().get(VKParameters.from(VKApiConst.OWNER_ID, "-100177655", VKApiConst.OFFSET, "2"));
        request.executeWithListener(new VKRequest.VKRequestListener() {
            @Override
            public void onComplete(VKResponse response) {
                super.onComplete(response);

                String jsonData = response.responseString;
                Log.v(TAG, "json is ready");

    // EXECUTE CODE IN MAIN UI THREAD:
final String final_json = jsonData;
runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //your code
textview.setText(final_json);
                    }
                });

                try {
                    Log.v(TAG, "before parsing");
                    parsePostsData(jsonData);
                    Log.v(TAG, "after parsing");
                } catch (JSONException e) {
                    Log.v(TAG, "EXCEPTION is thrown");
                    e.printStackTrace();
                }
            }
        });

        Log.v(TAG, "Finished Background Tasks");
        return null;
    }
Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
  • Sorry, but I didn't quite understand your solution. I don't want to run any of the methods given in the question on the main thread. As you can see I'm trying to download and prepare posts from some group in vk. When this process is being done in background I would like to show only progressBar. Could you please clarify your code? – Marat Aug 25 '16 at 11:36
  • The commented line '// YOUR CUSTOM CALLBACK' is the point of the 'ready' status. – Vyacheslav Aug 25 '16 at 11:44