简体   繁体   English

如何在Java中的不同线程中显示和隐藏一个视图?

[英]How to show and hide one view from diffrent threads in java?

I write my first java program for Android which draws some 3D functions (f(x,y)) using OpenGL, and the program is almost done but I experience problems with showing and hiding custom progress bar, developed as LinearLayout (which I created) with some text and progressBar. 我写了我的第一个Java程序,使用OpenGL绘制了一些3D函数(f(x,y)),这个程序差不多完成了,但是我遇到了显示和隐藏自定义进度条的问题,该进度条开发为LinearLayout(由我创建)带有一些文本和progressBar。 I need do make progressBarLL visible before and during calculating 3dfunction values. 我需要在计算3dfunction值之前和期间使progressBarLL可见。 To do this I implemented a handler in Graph3dActivity: 为此,我在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;

Then I have FuncSurf with its constructor doing long-lasting calculation of surface. 然后,我让FuncSurf及其构造函数对表面进行持久的计算。 I need to show my progressBarLL before calculations: 我需要在计算之前显示我的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);    
    }

The problem is that when I call function FuncSurf constructor from onClick event implemented in above Activity, then it results in showing progressBarLL for very short time and unfortunatelly after calculation is done, not before. 问题是,当我从上述Activity中实现的onClick事件中调用函数FuncSurf构造函数时,它将导致在很短的时间内显示progressBarLL,不幸的是在计算完成后而不是之前。 In other words handler handles messages after FuncSurf contructor is finished not simultaneously. 换句话说,处理程序在FuncSurf构造函数完成后无法同时处理消息。 This is probably because it is the same thread? 这可能是因为它是同一线程吗? But when the FuncSurf() constructor is called from Renderer everything is OK: 但是,当从Renderer调用FuncSurf()构造函数时,一切正常:

class MyOpenGLRenderer implements Renderer {
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            funcSurf = new FuncSurf(steps); //progressBarLL shown OK

My question is how to possibly neatly correct the code so that progressBarLL is shown before calculations in FuncSurf() constructor regardless from where I call this constructor? 我的问题是如何整齐地纠正代码,以便无论在哪里调用该构造函数,都在FuncSurf()构造函数中的计算之前显示progressBarLL? I cannot directly use progressBarLL.setVisibility in funcSurf because this is not GUI thread when called by onSurfaceChanged(...) above. 我不能在funcSurf中直接使用progressBarLL.setVisibility,因为当上述onSurfaceChanged(...)调用时,这不是GUI线程。 I'm sorry I couldn't explain the problem clearer. 对不起,我无法更清楚地说明问题。 I look forward to your help. 我期待着您的帮助。

Use AsyncTask , it's designed for exactly this case (and takes case of thread interaction without needing messages or anything like that). 使用AsyncTask ,它是专门为这种情况而设计的(并在不需要消息或类似信息的情况下进行线程交互)。

  • onPreExecute() runs in the UI thread, makes the progress bar visible. onPreExecute()在UI线程中运行,使进度条可见。
  • doInBackground() runs the long calculation in a background thread. doInBackground()在后台线程中运行长计算。 Regularly calls publishProgress() to notify progress. 定期调用publishProgress()通知进度。
  • onProgressUpdate() runs in the UI thread, and advances the progress bar. onProgressUpdate()在UI线程中运行,并前进进度栏。
  • onPostExecute() runs in the UI thread, and makes the progress bar invisible. onPostExecute()在UI线程中运行,并使进度条不可见。

See the documentation for Keeping your App Responsive , it includes a similar example (in which the long-running task is a network operation). 请参阅“ 使您的应用程序保持响应”的文档,其中包括一个类似的示例(长时间运行的任务是网络操作)。

Meanwhile I found "Thread construction" which solves the problem for now. 同时,我找到了“线程构造”,它现在可以解决问题。 It forces execution of "long-time task" in separate Thread, allowing GUI thread to continue and refresh the GUI by Handler. 它强制在单独的线程中执行“长期任务”,从而允许GUI线程继续执行并由Handler刷新GUI。 Small modification of the first fragment of code and the program seems to work OK now: 对代码的第一片段和程序进行小的修改现在看来可以正常工作:

Runnable run = new Runnable() 
{
    @Override
    public void run() {
        FuncSurf fs = new FuncSurf(steps);
        renderer.funcSurf =  fs;
    }
};       
Thread thr = new Thread(run);
thr.start();

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

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