简体   繁体   English

Java / Android等待线程完成后再运行新方法

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

I have an android application (written in java) which has two buttons ( connect and request data ). 我有一个Android应用程序(用java编写),它有两个按钮( 连接请求数据 )。

When each button is clicked, a task is performed and a progress dialog appears 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 connect button just has one task - run on the thread. 连接按钮只有一个任务 - 在线程上运行。 However, the request data button 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, progThread is 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) . 这里的关键方法是performAction(int type) I basically don't want this method to complete until progThread has finished running. 我基本上不希望这个方法完成,直到progThread完成运行。

As you can see, I've tried progThread.join() to prevent the method from continuing until progThread has finished running, however as progThread involves displaying a Progress Dialog , running progThread.join() seems to prevent the Progress Dialog from 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涉及显示进度对话框时 ,运行progThread.join()似乎阻止了进度对话框的显示,就像当前单击按钮时,第一个任务正在执行,但对话框仅在结束时闪烁。

Can anyone think of a way to run the thread, showing the Progress Dialog as normal and then running the second method (if there is one). 任何人都可以想到一种运行线程的方法,将Progress Dialog显示为正常,然后运行第二种方法(如果有的话)。

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

Android API provides an AsyncTask class which has two methods doInBackground and onPostExecute . Android API提供了一个AsyncTask ,它有两个方法doInBackgroundonPostExecute 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. 您必须覆盖它们,在doInBackground执行任何操作,并且当onPostExecute完成作业时,将运行回调。 There's also an onProgressUpdate callback which is exactly what you need. 还有一个onProgressUpdate回调,这正是你需要的。

Look at AsyncTask class. 看看AsyncTask类。 It should be able to do what you want. 它应该能够做你想要的。

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

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实现,只需在第一个线程的run方法结束时start()下一个线程。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM