Java / Android 在运行新方法之前等待线程完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11774294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 06:19:16  来源:igfitidea点击:

Java / Android wait until a thread has finished before running a new method

javaandroidmultithreading

提问by Pippa Rose Smith

I have an android application (written in java) which has two buttons (connectand request data).

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

When each button is clicked, a task is performed and a progress dialogappears to display how much the task has completed.

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

In order to show the progress dialog, when each button is clicked, the task is run on a thread.

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

The connectbutton just has one task - run on the thread. However, the request databutton executes two tasks - the first task on the thread similar to the connect button but also a second task, refreshInfo()which must be run after the first task on the thread, progThreadis finished.

连接按钮只是有一个任务-线程上运行。但是,请求数据按钮执行两个任务 - 线程上的第一个任务类似于连接按钮,但还有第二个任务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();
    }
}

The key method here is performAction(int type). I basically don't want this method to complete until progThreadhas finished running.

这里的关键方法是performAction(int type)。我基本上不希望这个方法在progThread运行完成之前完成。

As you can see, I've tried progThread.join()to prevent the method from continuing until progThreadhas finished running, however as progThreadinvolves displaying a Progress Dialog, running progThread.join()seems to prevent the Progress Dialogfrom showing, as currently when you click the button, the first task is performing but the dialog only flashes up at the end.

正如你所看到的,我已经尝试过progThread.join()来阻止方法在progThread完成运行之前继续,但是由于progThread涉及显示一个Progress Dialog,运行progThread.join()似乎阻止了Progress Dialog的显示,当前,当您单击按钮时,第一个任务正在执行,但对话框仅在最后闪烁。

Can anyone think of a way to run the thread, showing the Progress Dialogas normal and then running the second method (if there is one).

任何人都可以想出一种运行线程的方法,正常显示进度对话框,然后运行第二种方法(如果有的话)。

I've included the thread code below incase it is needed.

我在下面包含了线程代码,以防万一。

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;
    }
}

回答by devmiles.com

Android API provides an AsyncTaskclasswhich has two methods doInBackgroundand onPostExecute. You'll have to override both of them, do whatever you have to do in doInBackgroundand when the job is done onPostExecutecallback will be run. There's also an onProgressUpdatecallback which is exactly what you need.

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

回答by jsstp24n5

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

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

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

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

回答by josephus

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

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

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.

但是,如果您想继续执行 Thread 实现,只需start()在第一个线程的 run 方法结束时执行下一个线程即可。

回答by Andreas Petersson

Sounds like you need to use a CountdownLatchof size 1

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