Question

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;
}
Was it helpful?

Solution

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.

OTHER TIPS

Hay Can you Try to use Handler?

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

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);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top