4

2つのボタン(接続データの要求)を持つAndroidアプリケーション(Javaで記述)があります。

各ボタンをクリックすると、タスクが実行され、進行状況ダイアログが表示され、タスクがどれだけ完了したかが示されます。

進行状況ダイアログを表示するために、各ボタンがクリックされると、タスクはスレッド上で実行されます。

接続ボタンには、スレッド上で実行するという1つのタスクしかありません。ただし、データ要求ボタンは2つのタスクを実行します。接続ボタンに似たスレッドの最初のタスクだけでなく、スレッドの最初のタスクprogThreadの終了後に実行する必要がある2番目のタスクrefreshInfo()も実行します。

private Button connectButton;
private Button requestDataButton;

private ProgressDialog connectionDialog;
private ProgressDialog requestDataDialog;

private ProgressThread progThread;

private int currentDialog;

public void connectClick(View view)      //When the connect button is clicked
{
    performAction(1);   //Run the thread to perform the action
}

public void requestDownloadClick(View view)   //When the request data button is clicked
{
    performAction(2);    //Run the thread to perform the action

    refreshInfo();    //Do something else
}

private void performAction(int type)
{
    currentDialog = type;

    showDialog(type);

    try 
    {
        progThread.join();
    } 
    catch (InterruptedException e) 
    {
        e.printStackTrace();
    }
}

ここでの重要なメソッドはperformAction(int type)です。基本的に、 progThreadの実行が終了するまでこのメソッドを完了させたくありません。

ご覧のとおり、progThread.join()を実行して、 progThreadの実行が終了するまでメソッドが続行されないようにしましたが、 progThreadには進行状況ダイアログの表示が含まれるため、 progThread.join()を実行すると、進行状況ダイアログが表示されないようです。現在ボタンをクリックすると、最初のタスクが実行されますが、ダイアログは最後にのみ点滅します。

スレッドを実行する方法を考えて、進行状況ダイアログを通常どおりに表示してから、2番目のメソッド(存在する場合)を実行することはできますか?

必要な場合に備えて、以下のスレッドコードを含めました。

private class ProgressThread extends Thread 
{   
    final static int DONE = 0;
    final static int RUNNING = 1;   // Class constants defining state of the thread

    private Handler progressHandler;
    int mState;
    int total;

    ProgressThread(Handler _handler)    // Constructor with an argument that specifies Handler on main thread to which messages will be sent by this thread.
    {
        progressHandler = _handler;
    }

    public void run()    // Invoked automatically when the Thread starts.  
    {
        mState = RUNNING;   

        updateProgressBar();

        connectButton = (Button) findViewById(R.id.btnConnect);
        requestDataButton = (Button) findViewById(R.id.btnRequestDownload);

        while (mState == RUNNING) 
        {
            if (currentDialog == 1)
            {
                try
                { 
                    doSomething();

                    if (something)
                    {
                        setState(DONE);

                        total = 100;

                        updateProgressBar();

                        removeDialog(1);

                        connectButton.setEnabled(false);
                    }
                    else
                    {
                        total = total + 20;

                        if (something has reached a limit)
                        {
                            setState(DONE);

                            total = 0;

                            updateProgressBar();

                            removeDialog(1); 
                        }
                    }

                    updateProgressBar();
                }
                catch (Exception e)
                {

                }
            }

            if (currentDialog == 2)
            {
                try
                {
                    doSomething();

                    total = 10;

                    updateProgressBar();

                    doSomething();

                    total = 70;

                    updateProgressBar();

                    if (something)  //If the download info has not been got
                    {
                        setState(DONE);

                        total = 0;

                        updateProgressBar();

                        removeDialog(2);

                        runOnUiThread(new Runnable()
                        {
                            public void run() 
                            {
                                connectButton.setEnabled(true);

                                requestDataButton.setEnabled(true);
                            }                               
                        });  
                    } 
                    else
                    {
                        total = 100;

                        updateProgressBar();

                        setState(DONE);

                        removeDialog(2);

                        runOnUiThread(new Runnable()
                        {
                            public void run() 
                            {
                                requestDataButton.setEnabled(false);
                            }                               
                         }); 
                     }
                }
                catch (Exception e)
                {
                    removeDialog(2);

                    setState(DONE);

                    runOnUiThread(new Runnable()
                    {
                        public void run() 
                        {
                            connectButton.setEnabled(true);

                            requestDataButton.setEnabled(true);
                        }                               
                    });  
                }
            }
        }
    }

    // Set current state of thread (use state=ProgressThread.DONE to stop thread)
    public void setState(int state) 
    {
        mState = state;
    }

    public void updateProgressBar()
    {
        Message msg = progressHandler.obtainMessage();   // Send message (with current value of  total as data) to Handler on UI thread so that it can update the progress bar

        Bundle b = new Bundle();

        b.putInt("total", total);

        msg.setData(b);

        progressHandler.sendMessage(msg);
    }
}

final Handler handler = new Handler()     // Handler on the main (UI) thread that will receive messages from the second thread and update the progress.
{
    public void handleMessage(Message msg) 
    {
        int total = msg.getData().getInt("total");             // Get the current value of the variable total from the message data and update the progress bar

        switch (currentDialog)
        {
        case 1 : 
            connectionDialog.setProgress(total);
            break;

        case 2 : 
            requestDataDialog.setProgress(total);
            break;
        }
    }
};

protected Dialog onCreateDialog(int id) 
{   
    switch (currentDialog)
    {
    case 1 :
        connectionDialog = new ProgressDialog(this);

        connectionDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

        connectionDialog.setMax(100);

        connectionDialog.setProgress(0);

        connectionDialog.setMessage("Connecting To The Device");

        progThread = new ProgressThread(handler);

        progThread.start();

        return connectionDialog;

    case 2 :
        requestDataDialog = new ProgressDialog(this);

        requestDataDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

        requestDataDialog.setMax(100);

        requestDataDialog.setProgress(0);

        requestDataDialog.setMessage("Requesting Download Data");

        progThread = new ProgressThread(handler);

        progThread.start();

        return requestDataDialog;

    default : 
        return null;
    }
}
4

4 に答える 4

6

Android API provides an AsyncTask class which has two methods doInBackground and onPostExecute. You'll have to override both of them, do whatever you have to do in doInBackground and when the job is done onPostExecute callback will be run. There's also an onProgressUpdate callback which is exactly what you need.

于 2012-08-02T09:28:06.990 に答える
2

Look at AsyncTask class. It should be able to do what you want.

http://developer.android.com/reference/android/os/AsyncTask.html

于 2012-08-02T09:24:40.907 に答える
0

Seems other answers have you covered. AsyncTask is the way to go.

However if you want to push through with your Thread implementation, just start() the next thread at the end of the first thread's run method.

于 2012-08-02T09:35:29.760 に答える
0

Sounds like you need to use a CountdownLatch of size 1

于 2012-08-02T09:51:05.083 に答える