【问题标题】:Java / Android wait until a thread has finished before running a new methodJava / Android 在运行新方法之前等待线程完成
【发布时间】:2012-08-02 09:06:01
【问题描述】:

我有一个 android 应用程序(用 java 编写),它有两个按钮(connectrequest data)。

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

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

connect 按钮只有一项任务——在线程上运行。但是,request data 按钮执行两个任务 - 线程上的第一个任务类似于连接按钮,但还有第二个任务 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;
    }
}

【问题讨论】:

  • 读取Java同步,等待对象,需要正确理解JAVA才能按顺序运行线程。

标签: java android multithreading


【解决方案1】:

Android API 提供了一个AsyncTask class,它有两个方法doInBackgroundonPostExecute。你必须覆盖它们,在doInBackground 中做任何你必须做的事情,当工作完成时,onPostExecute 回调将运行。 还有一个 onProgressUpdate 回调正是您所需要的。

【讨论】:

  • 谢谢,真的很有帮助:)
【解决方案2】:

查看 AsyncTask 类。它应该能够为所欲为。

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

【讨论】:

  • 谢谢,真的很有帮助:)
【解决方案3】:

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

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

【讨论】:

  • 谢谢,我要试试异步任务:)
【解决方案4】:

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

【讨论】:

    猜你喜欢
    • 2016-03-13
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    相关资源
    最近更新 更多