5

This is my fist stackoverflow post so please be gentle with me! I'm sure that what i'm trying to do is possible and it is something I have done (or not done?) that is causing the problem... I'm just not sure what that something is.

What i'm trying to do:
Show a ProgressDialog while my app synchronises and processes the downloaded data.

The problem:
The ProgressDialog shows but doesn't spin (which makes it look like it has frozen), the synchronisation and processing happens, the ProgressDialog closes, the app continues as normal.

How I am currently tring to do that:
Create a ProgressDialog - in my Activity
Do the synchronisation - in my Service
Process the data - in my Service
Dismis the ProgressDialog - in my Activity

The things I have tried:
Using a Thread (code below) Using a AsynTask (can provide code if needed) Using a Handler (can provide code if needed)

After spending lots of time searching for the answer to my question it seems others have had the same or similar problem and managed to solve it using one of the ideas above. However I have been unable to implement any of these ideas to solve my particular issue. This makes me sure that it is something I am doing wrong... I'm just not sure what.

The original code I wrote and am using as a basis for all my attempted fixes:
First

public class myActivity extends ListActivity {
    private ProgressDialog dialog;
    private boolean mIsBound;
    private myService mBoundService;
    private ServiceConnection mConnection;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*if we need to login start login activity for result*/
        ...
    }

    ...
    /*other methods*/
    ...
}

then

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    switch (requestCode){
        case ACTIVITY_LOGIN:
            /*after login we know we always need to sync*/
         dialog = new ProgressDialog(myActivity.this);
         dialog.setMessage("Synchronising...");
         dialog.setIndeterminate(true);
         dialog.setCancelable(false);
         dialog.show();

            Thread doBind = new Thread(new Runnable(){public void run(){doBindService();}});
            doBind.start();
            break;
    }
}

so now i am assuming that doBind is happening in a different thread leaving the UI thread with nothing to do other than show the ProgressDialogue...?

private boolean doBindService() {
 mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mBoundService = ((myService.LocalBinder)service).getService();      
            while (mBoundService.isRunning()){
                /*wait for service to finish before doing anything else... myMethod() is expecting the sync to have completed*/
                /*I suspect this loop to be the thing causing the problem. But I'm not sure why because it is in a different thread so shouldn't interfear with the dialog?! And if that is what is causing the problem then how else can I do this?*/
            }
            /*get the activity to do Stuff with the downloaded data*/
            myMethod();
            /*finished with the service for now so unbind*/
            doUnbindService();
            if (dialog != null) {
                dialog.dismiss();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            mBoundService = null;
        }
    };

    boolean myReturn = bindService(new Intent(myActivity.this, myService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = myReturn;
 return myReturn;
}

private void doUnbindService() {
    if (mIsBound) {
        unbindService(mConnection);
        mIsBound = false;
    }
}

Please let me know if you require any further information in order to assist me with this issue.


EDIT:

Here is the code I am using to use a handler instead. This displays the same behavior (spinner doesn't spin) as before.

Thread doBind = new Thread(new Runnable(){
    public void run(){
        doBindService();
    }
});
doBind.start();

.

private Handler handler = new Handler() {
    @Override
public void handleMessage(Message msg) {
    dialog.dismiss();
}
};

.

private boolean doBindService() {
 mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mBoundService = ((myService.LocalBinder)service).getService();      
            while (mBoundService.isRunning()){
            }
            //...do stuff same as before...
            handler.sendEmptyMessage(0);
        }

        public void onServiceDisconnected(ComponentName className) {
            mBoundService = null;
        }
    };

    boolean myReturn = bindService(new Intent(myActivity.this, myService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = myReturn;
 return myReturn;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
John
  • 1,466
  • 3
  • 21
  • 38
  • I see this same freezing behavior on my progress dialog. It's usually when the task is almost finished and the dialog is about to close. For how long is your dialog up? If you make the thread sleep for a few sec, does that make the dialog spin? – softarn Nov 17 '10 at 12:31
  • I have a similar problem with ProgressDialog that I asked about here: http://stackoverflow.com/questions/3821306/progressdialog-created-from-oncreatedialog-stops-animating-on-second-run. I think there's a bug in the Android codebase. – ageektrapped Nov 17 '10 at 12:40
  • @softarn: Thanks for the suggestion. If I do: Thread doBind = new Thread(new Runnable(){ public void run(){ try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } doBindService(); } }); The the dialog spins for 10 seconds then freezes for 3 to 4 seconds before disapearing... – John Nov 17 '10 at 12:54
  • Like ageektrapped sayed, it seems to be a bug then. Before i read question I hadn't really noticed this. Now it's really bothering me :) Issue: http://code.google.com/p/android/issues/detail?id=4266 – softarn Nov 17 '10 at 13:41
  • 1
    +1 for well done first question – WarrenFaith Nov 17 '10 at 15:47
  • Agreed with WarrenFaith, this is the information that should be given for all sufficiently complex questions. – I82Much Nov 17 '10 at 16:05

3 Answers3

2

The problem with the spinner is related to the ServiceConnection which you create in the new thread. unfortunately for you, this will be run on your main thread / gui thread.

From the API reference: (http://developer.android.com/reference/android/content/ServiceConnection.html)

Like many callbacks from the system, the methods on this class are called from the main thread of your process.

So, since I'm not familiar with services I can only guess that one way of communicating when your service is done downloading data would be to broadcast an Intent which you listen for in your Activity, and then stop the ProgressDialog. But there are certainly other ways as well.

And as a side note, you should never modify the gui from any thread other then the main thread, which you're trying to do by spawning a new Thread which tries to dismiss the dialog. You should only dismiss the dialog from the main thread.

Cpt.Ohlund
  • 2,589
  • 1
  • 20
  • 15
  • I am investigating your suggestion (sending and reacting to an intent) and at the moment it is looking like this is the answer to my problem. Howerver you say in your post "there are certainly other ways as well." ... What are these other ways? Would any of these be a "better" way of doing this? – John Nov 17 '10 at 16:58
  • Using your suggestion I found this post: http://stackoverflow.com/questions/2843874/in-android-how-to-call-function-of-activity-from-a-service and now have a working app. Thanks for your help! – John Nov 17 '10 at 17:33
0

Hay Can you Try to use Handler?

I think you should do this by using Handler function of Android

Piyush
  • 2,589
  • 6
  • 38
  • 77
  • Hi. Thanks for your suggestion. I have tried implementing a handler to do this but I'm not clear on where the call to it should be and what it should actually do. My current implementation still displays the same problem as described when using a thread. I used the example as seen on http://www.helloandroid.com/tutorials/using-threads-and-progressdialog. I'll edit my original post and add the the code I've tried. If you could take a look and see what i'm doing wrong i'll appreciate it. – John Nov 17 '10 at 14:58
0
public class yourclass extends Activity implements Runnable {

    static ProgressDialog progressDialog;

    @Override
    public void onCreate(Bundle icicle) {
                progressDialog = ProgressDialog.show(keywordview.this, "", "Loading...", true);
                Thread thread = new Thread(keywordview.this);

    }
    final Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            progressDialog.dismiss();
        /*Here you can handle you process*/
        }
    };

    public void run() {
        //here your code for run 
        handler.sendEmptyMessage(0);
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Piyush
  • 2,589
  • 6
  • 38
  • 77