0

Posting a question for the first time here. Just started programming and coding my first app.

I have an Application class file that has the method fetchUpdates():

public synchronized void fetchUpdates() {
    String[] mURLs = getURLs();
    new DownloadJSONData().execute(mURLs[0], mURLs[1]);
}

DownloadJSONData is an asyncTask that gets updates from the server and the onPostExecute method updates an sqlite database using a JSON array from the server.

Different components (widgets and activities) of the app call this method to get updates from the server to update the database.

The question: Does synchronized method run on a separate thread from the UI thread? If so, there should be no problem in moving the code in the DownloadJSONData to the synchronized fetchUpdates() method right? And if there is a holdup in connecting to the server or downloading the data from the server, it shouldn't block the UI thread right?

The motive: I'm trying to change the fetchUpdates() method to return a boolean indicating whether the database was updated or not. However, as it is now (I think) fetchUpdates() method finishes before the asyncTask's onPostExecute method and, hence, fetchUpdates() method cannot indicate whether the call to DownloadJSONData() updated the database. I need the app components that call the fetchUpdates() method to behave differently if the database was updated after the call.

P.S. Since I'm new to programming simple and detailed explanations would be really helpful.

Thanks!

fahmy
  • 3,543
  • 31
  • 47
  • I have a question for you. Why aren't you updating your database in the `AsyncTask`'s `doInBackground()` method? Because the `onPostExecute()` runs on the UI Thread and it might cause a hickup. – tolgap Mar 19 '13 at 09:46
  • That's a good point. I'll bring about the change. Didn't think about that when I wrote the code. Thanks for pointing that out! – fahmy Mar 19 '13 at 09:50

2 Answers2

6

No, a synchronized method runs in the same thread. However, no other thread can execute another synchronized method (of the same object) while it is being executed.

drew moore
  • 31,565
  • 17
  • 75
  • 112
1

Using AsyncTask means that most of the time the calling method will not know the result right away - unless you call AsyncTask.get() but you don't want to do that and loose the asynchronous aspect. Let's say that you want to display a message to the user when the database has been updated what you should do is start the AsyncTask and let it handle the return status of the database update by overriding the correct method. I would also separate the request to the server and database update in two distinct tasks:

    public class CallServer extends AsyncTask<String, Void, Void> {

    @Override
    protected Void doInBackground(String... params) {
        // Do your request to the server
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        if (result == SUCCESS) {
            // Display message to indicate successful request
            new UpdateDatabase().execute(params);
        } else {
            // Display error message or whatever you want to do 
        }
    }
}

public class UpdateDatabase extends AsyncTask<String, Void, Void> {

    @Override
    protected Void doInBackground(String... params) {
        // Update the DB
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        if (result == SUCCESS) {
            // Display success message or whatever you want to do 
        } else {
            // Display error message or whatever you want to do 
        }
    }
}

The main idea is that the AsyncTask should handle the error/success cases and not its caller.

El Bert
  • 2,958
  • 1
  • 28
  • 36
  • I have a service that call `fetchUpdates()` methods at a given interval to check for updates to update the database. Suppose I make a toast when failed to connect to server. The toast would popup even when the app is not in focus at the set intervals. Ideally I want the toast to popup only **once** when the user open the app (the MainActivity.class call `fetchUpdates()` on onCreate). – fahmy Mar 19 '13 at 10:10
  • Then you could display the status message only when called from you main activity and doing nothing when called from the service by passing a parameter to your AsyncTask. For calling it only when the application is open your could take a look at http://stackoverflow.com/a/151940/2003420 – El Bert Mar 19 '13 at 10:42