Running the code after an asynchronous task

1.6k Views Asked by At

So I am looking for a way to run only a block of code to run after an asynchronous task(s) have finished. The code is related to the Request.executeAsync(); in the facebooksdk for android. The code that I going to use for the explanation is:

public class Home extends Activity {

    TextView welcomeTextView;
    private JSONObject userProfile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        userProfileFetched = false;

        welcomeTextView = (TextView)findViewById(R.id.welcome);
        populateUserProfile();
        Log.d("USER_PROFILE", userProfile.toString()); //NullPointerException occurs here
    }

    private void populateUserProfile() {
        Request.newMeRequest(Session.getActiveSession(), new Request.GraphUserCallback() {
            @Override
            public void onCompleted(GraphUser user, Response response) {
                userProfile = response.getGraphObject().getInnerJSONObject();
            }
        }).executeAsync();
    }
}

The line with the comment above points the line on which my app shuts down unexpectedly. When I first start the activity the onCreate method is called with some house keeping stuff. Then a function populateUserProfile() is called which executes a me request asynchronously. If I log the response.getGraphObject().getInnerJSONObject().toString() being in the onCompleted() function, I could clearly see the perfect result that I am looking for, the JSONObject for the logged in user but, as in the code above, if I assign that function's return value to the userProfile variable and then log it after the call of the function in the onCreate() method then my app stops unexpectedly and a NullPointerException is thrown at the Log line.

I know that this is happening because the me request is not yet completed while I log the userProfile JSONObject and that is why it's not assigned to anything yet, so I need to know how could I wait for the onCompleted method in the populateUserProfile() function so that the userProfile object could be successfully assigned to the info of the logged in user?

In other words, how could I wait for the asynchronous task of the me request to get finished and then log userProfile into the LogCat?

Hope I am clear and looking forward to an explanatory answer.

2

There are 2 best solutions below

6
On

A solution that comes to mind is to use AsyncTask < T, T, T> and then call your function in the onPostExecute method.

EDIT: This an example from developers, don't look what it does, just understand the concept. In the doInBackground method all the timetaking work is done, when it is finished it calls onPostExecute, hence you can safely assume that inside it all the Internet work is done and you can continue.

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
 protected Long doInBackground(URL... urls) {
     int count = urls.length;
     long totalSize = 0;
     for (int i = 0; i < count; i++) {
         totalSize += Downloader.downloadFile(urls[i]);
         publishProgress((int) ((i / (float) count) * 100));
         // Escape early if cancel() is called
         if (isCancelled()) break;
     }
     return totalSize;
 }

 protected void onProgressUpdate(Integer... progress) {
     setProgressPercent(progress[0]);
 }

 protected void onPostExecute(Long result) {
     showDialog("Downloaded " + result + " bytes");
     // here you call the function, the task is ended.

 }}
3
On
populateUserProfile(){

new AsyncTask<Void, Void, JSONObject>() {

        @Override
        protected JSONObject doInBackground(Void params) {
           return response.getGraphObject().getInnerJSONObject();
        }

        @Override
        protected void onPostExecute(JSONObject result) {
           Log.d("USER_PROFILE", result.toString());
        }

    }.execute();
}