我有一个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 < / strong>涉及显示进度对话,运行 progThread.join()似乎阻止显示进度对话,就像当前单击时一样按钮,第一个任务正在执行,但对话框仅在结束时闪烁。
任何人都可以想到一种运行线程的方法,正常显示进度对话框,然后运行第二种方法(如果有的话)。
我已经在下面包含了线程代码,因为它是必需的。
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;
}
}
答案 0 :(得分:6)
Android API提供了AsyncTask
class,它有两种方法doInBackground
和onPostExecute
。您必须覆盖它们,在doInBackground
中执行任何操作以及完成作业时onPostExecute
将运行回调。
还有onProgressUpdate
回调,这正是您所需要的。
答案 1 :(得分:1)
查看AsyncTask类。它应该能够做你想做的事。
http://developer.android.com/reference/android/os/AsyncTask.html
答案 2 :(得分:0)
似乎还有其他答案。 AsyncTask是要走的路。
但是如果你想要完成你的Thread实现,只需start()
第一个线程的run方法结束时的下一个线程。
答案 3 :(得分:0)
听起来你需要使用大小为1的CountdownLatch