我编写了我的第一个用于Android的java程序,它使用OpenGL绘制了一些3D函数(f(x,y)),程序几乎已经完成但我遇到了显示和隐藏自定义进度条的问题,开发为LinearLayout(其中我创建了一些text和progressBar。 我需要在计算3dfunction值之前和期间使progressBarLL可见。 为此,我在Graph3dActivity中实现了一个处理程序:
public class Graph3dAct extends Activity {
(...)
static ProgressBar progressBarPB;
static LinearLayout progressBarLL;
public static Handler progressHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e("HANDLER:",Integer.toString(msg.arg1));
//toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 500);
switch (msg.arg1)
{
case 1: progressBarLL.setVisibility(LinearLayout.VISIBLE);
break;
case 2: progressBarLL.setVisibility(LinearLayout.INVISIBLE);
break;
case 3: progressBarPB.setProgress(msg.arg2);
//to be implemented
break;
default: Log.e("Graph3dAct","Handler misused;");
}
progressBarLL.invalidate();
progressBarPB.invalidate();
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
progressBarPB = (ProgressBar) findViewById(R.id.surface3dPB);
progressBarLL = (LinearLayout) findViewById(R.id.progressLL);
(...)
final Button moreStepsB = (Button) findViewById(R.id.buttonMoreS);
moreStepsB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int max=stepsVals.length-1;
if (stepsIndex<max)
{
stepsIndex++;
steps=stepsVals[stepsIndex];
FuncSurf fs = new FuncSurf(steps);
renderer.funcSurf = fs;
然后我让FuncSurf和它的构造函数进行持久的表面计算。我需要在计算之前显示我的progressBarLL:
public class FuncSurf {
public FuncSurf(int steps_) {
Log.e("FuncSurf","CONSTRUCTOR");
Message msg = new Message();
msg.arg1=1; //instruct handler to show progress layout: progressBarLL
Graph3dAct.progressHandler.sendMessage(msg);
(...) HERE GOES LONG-LASTING CALCULATION
msg = new Message();
msg.arg1=2; //instruct handler to hide progress layout: progressBarLL
Graph3dAct.progressHandler.sendMessage(msg);
}
问题在于,当我从上面的Activity中实现的onClick事件调用函数FuncSurf构造函数时,它会导致显示progressBarLL很短的时间,并且在计算完成之后不幸,而不是之前。换句话说,处理程序在FuncSurf构造函数不同时完成后处理消息。这可能是因为它是同一个线程? 但是当从Renderer调用FuncSurf()构造函数时,一切正常:
class MyOpenGLRenderer implements Renderer {
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
funcSurf = new FuncSurf(steps); //progressBarLL shown OK
我的问题是如何整齐地纠正代码,以便在FuncSurf()构造函数中计算之前显示progressBarLL,无论我在何处调用此构造函数? 我不能直接在funcSurf中使用progressBarLL.setVisibility,因为当上面的onSurfaceChanged(...)调用时,这不是GUI线程。 对不起,我无法解释问题的清晰度。 我期待着你的帮助。
答案 0 :(得分:1)
使用AsyncTask
,它专为这种情况而设计(并且需要线程交互而不需要消息或类似的东西)。
onPreExecute()
在UI线程中运行,使进度条可见。doInBackground()
在后台线程中运行长计算。定期致电publishProgress()
以通知进度。onProgressUpdate()
在UI线程中运行,并推进进度条。onPostExecute()
在UI线程中运行,并使进度条不可见。请参阅Keeping your App Responsive的文档,它包含一个类似的示例(长时间运行的任务是网络操作)。
答案 1 :(得分:0)
与此同时,我发现&#34;螺纹结构&#34;这解决了现在的问题。它强制执行&#34;长期任务&#34;在单独的Thread中,允许GUI线程继续并由Handler刷新GUI。对代码的第一个片段和程序的小修改似乎现在可以正常工作:
Runnable run = new Runnable()
{
@Override
public void run() {
FuncSurf fs = new FuncSurf(steps);
renderer.funcSurf = fs;
}
};
Thread thr = new Thread(run);
thr.start();