4

我有一个 android 应用程序(用 java 编写),它有两个按钮(连接请求数据)。

单击每个按钮时,将执行一项任务并出现一个进度对话框以显示任务已完成的程度。

为了显示进度对话框,当单击每个按钮时,任务在线程上运行。

连接按钮只有一项任务——在线程上运行。但是,请求数据按钮执行两个任务 - 线程上的第一个任务类似于连接按钮,但还有第二个任务refreshInfo(),它必须在线程上的第一个任务progThread完成之后运行。

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涉及显示Progress Dialog,运行progThread.join()似乎阻止了Progress Dialog显示,目前,当您单击按钮时,第一个任务正在执行,但对话框仅在最后闪烁。

谁能想到一种运行线程的方法,正常显示进度对话框,然后运行第二种方法(如果有的话)。

我在下面包含了线程代码,以防需要。

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 提供了一个AsyncTask,它有两个方法doInBackgroundonPostExecute. 你必须覆盖它们,做任何你必须做的事情doInBackground,当工作完成时,onPostExecute回调将被运行。还有一个onProgressUpdate回调正是您所需要的。

于 2012-08-02T09:28:06.990 回答
2

查看 AsyncTask 类。它应该能够做你想做的事。

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

于 2012-08-02T09:24:40.907 回答
0

听起来您需要使用大小为 1的CountdownLatch

于 2012-08-02T09:51:05.083 回答
0

似乎您已经涵盖了其他答案。AsyncTask 是要走的路。

但是,如果您想推进您的 Thread 实现,只需start()在第一个线程的 run 方法末尾的下一个线程即可。

于 2012-08-02T09:35:29.760 回答