android UI元素的可见性不变

时间:2019-05-31 09:09:16

标签: java android user-interface

我一直在编写用于FTP文件传输的应用程序,我需要隐藏一些UI元素并在单击按钮时使一些可见。可见性设置与应用程序启动时相同,并且不会更改。知道为什么吗?

这是我的元素:

ip= (EditText) findViewById(R.id.ipadd);
portt=(EditText) findViewById(R.id.port);
conn= (Button) findViewById(R.id.connectb);
pb= (ProgressBar) findViewById(R.id.pb);
trans=(TextView) findViewById(R.id.transfer);

以下是应用程序(onCreate)启动时的设置:

pb.setVisibility(View.INVISIBLE);
trans.setVisibility(View.INVISIBLE);
ip.setVisibility(View.VISIBLE);
portt.setVisibility(View.VISIBLE);
conn.setVisibility(View.VISIBLE);

将应用这些设置。 这是单击按钮时该功能的代码:

Ftp ftp;
errflag=false;
ip.setVisibility(View.INVISIBLE);
portt.setVisibility(View.INVISIBLE);
conn.setVisibility(View.INVISIBLE);
trans.setVisibility(View.VISIBLE);
pb.setVisibility(View.VISIBLE);
while(!errflag) {
    try{
      ftp=new Ftp();
      String result = ftp.execute("hi").get();
      if(result.equals("Finished"))
          break;
    } catch(Exception e){
        e.printStackTrace();
    }
}

代码中的所有内容都可以正常工作,但这些元素的可见性除外。 该控件进入while循环并正确退出,但不会更改元素的可见性。是的,该函数在单击按钮时调用,因此它在UI线程中,但是我仍然尝试将代码包装在runOnUIThread中似乎没有任何改变的方法。 任何意见将不胜感激。

异步任务代码:

public class Ftp extends AsyncTask<String ,String,String>
{

    protected String doInBackground(String... urls)
    {
        try
        {
            String ipadd= ip.getText().toString();
            int port =Integer.parseInt(portt.getText().toString());
            Socket socket=new Socket(ipadd,port);
            //Button conn=(Button) findViewById(R.id.connectb);

            //conn.setEnabled(false);
            BufferedReader br= new BufferedReader(new InputStreamReader(socket.getInputStream()));
            BufferedOutputStream bo= new BufferedOutputStream(socket.getOutputStream());
            PrintWriter pw= new PrintWriter(bo,true);
            String file=br.readLine();
            if(file.equals("Finished"))
                return file;
            File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
            File f= new File(path, "/" + file);
            byte[] buff= new byte[1024];
            int len;
                pw.println("done");
                DataInputStream is= new DataInputStream(socket.getInputStream());
                FileOutputStream fos= new FileOutputStream(f);

            Thread.sleep(1);
            publishProgress(file);
                while((len=is.read(buff))!=-1)
                {



                    fos.write(buff,0,len);

                }
            Log.i("status","Finsihed");


           /* else
            {
                Toast.makeText(MainActivity.this,"File already exists!",Toast.LENGTH_LONG).show();
            }*/
        }catch(NumberFormatException nfe)
        {
            errflag=true;
            runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
                }
            });
            nfe.printStackTrace();

        }
        catch(java.net.UnknownHostException un)
        {
            errflag=true;
            runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
                }
            });
            //Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
            un.printStackTrace();
        }
        catch(java.net.NoRouteToHostException no)
        {errflag=true;

            runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(MainActivity.this,"There is no active server at the specified IP and port!",Toast.LENGTH_LONG).show();
                }
            });
            no.printStackTrace();
        }
        catch(Exception e)

        {
            errflag=true;
            Log.i("this","error");
            e.printStackTrace();
        }
        return "Not Yet";
    }
    protected void onProgressUpdate(String... para)
    {
        super.onProgressUpdate(para);
        trans.setText("Transfering file: "+para[0]);


    }

}`

然后我创建了一个新线程:

public class MyThread extends Thread
{
    public void run() {
        while (!errflag) {
            try {
                Ftp ftp = new Ftp();
                String res = ftp.execute("hi").get();
                if (res.equals("Finished"))
                    break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

并将功能代码更改为:

errflag=false;
            ip.setVisibility(View.INVISIBLE);
            portt.setVisibility(View.INVISIBLE);
            conn.setVisibility(View.INVISIBLE);
            trans.setVisibility(View.VISIBLE);
            pb.setVisibility(View.VISIBLE);

        /*ftp=new Ftp();
        String result = ftp.execute("hi").get();
        if(result.equals("Finished"))
            break;*/

        try {
            MyThread t = new MyThread();
            t.start();
        }catch(Exception ex)
        {
            ex.printStackTrace();
        }

4 个答案:

答案 0 :(得分:1)

我认为,您应该将while循环移到另一个线程中。 更改可见性意味着视图层次结构将在下一帧重绘,并且[可见性]仅在下一次绘制迭代时才考虑在内。因此,当您阻塞ui线程(在while循环中)时,将永远无法达到此重绘阶段。

UPD:您应该释放UI线程,因此只需在另一个线程中循环运行即可。

ip.setVisibility(View.INVISIBLE);
portt.setVisibility(View.INVISIBLE);
conn.setVisibility(View.INVISIBLE);
trans.setVisibility(View.VISIBLE);
pb.setVisibility(View.VISIBLE);
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
    @Override
    public void run() {
        errflag=false;
        while(!errflag) {
            try{
              ftp=new Ftp();
              String result = ftp.execute("hi").get();
              if(result.equals("Finished"))
                  break;
            } catch(Exception e){
                e.printStackTrace();
            }
        }
    }
});

答案 1 :(得分:1)

感谢您的帮助。我找到了解决方案。显然,将繁重的工作放在另一个普通线程上不会改变任何事情。AsyncTasks是为此目的而设计的。 我读了这篇文章:https://tekeye.uk/android/examples/asynctask-helps-avoid-anr 我将while循环放入另一个asynctask类中,并在“ onPreExecute()”中进行了UI更改,然后将循环放入“ doInBackground()”中。它的工作原理很吸引人。 这是我的代码:

class HeavyWork extends AsyncTask<String,Void,Void>
{
    protected void onPreExecute()
    {
        pb.setVisibility(View.VISIBLE);
        trans.setVisibility(View.VISIBLE);
        ip.setVisibility(View.INVISIBLE);
        portt.setVisibility(View.INVISIBLE);
        conn.setVisibility(View.INVISIBLE);
    }
    protected Void doInBackground(String... urls)
    {
        start();
    return null;
    }
    protected void onPostExecute(Void a)
    {
        pb.setVisibility(View.INVISIBLE);
        trans.setVisibility(View.INVISIBLE);
        ip.setVisibility(View.VISIBLE);
        portt.setVisibility(View.VISIBLE);
        conn.setVisibility(View.VISIBLE);
        trans.setText("Waiting for files");
    }


}

启动方法是:

 public void start()
{
    while (!errflag) {
        try {
            Ftp ftp = new Ftp();
            String res = ftp.execute("hi").get();
            if (res.equals("Finished"))
                break;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后我将onClick方法更改为:

errflag=false;

        /*ftp=new Ftp();
        String result = ftp.execute("hi").get();
        if(result.equals("Finished"))
            break;*/

        new HeavyWork().execute("hi");

但是似乎您无法从另一个asynctask线程调用asynctask,因此您需要从UI线程调用它。 为此,我从doInBackground删除了start并将其粘贴在onPostExecute上,因为它在UI线程上运行,如下所示:

class HeavyWork extends AsyncTask<String,Void,Void>
{
    protected void onPreExecute()
    {
        pb.setVisibility(View.VISIBLE);
        trans.setVisibility(View.VISIBLE);
        ip.setVisibility(View.INVISIBLE);
        portt.setVisibility(View.INVISIBLE);
        conn.setVisibility(View.INVISIBLE);
    }
    protected Void doInBackground(String... urls)
    {

    return null;
    }
    protected void onPostExecute(Void a)
    {
        start();
        pb.setVisibility(View.INVISIBLE);
        trans.setVisibility(View.INVISIBLE);
        ip.setVisibility(View.VISIBLE);
        portt.setVisibility(View.VISIBLE);
        conn.setVisibility(View.VISIBLE);
        trans.setText("Waiting for files");
    }


}

就是这样。有效。

非常感谢你们,尤其是亚历山大和尼古拉。您真是太好了:)

答案 2 :(得分:0)

尝试在如下所示的工作线程中执行ftp方法,可能是您阻止了UI的更新。

Ftp ftp;
errflag=false;
ip.setVisibility(View.INVISIBLE);
portt.setVisibility(View.INVISIBLE);
conn.setVisibility(View.INVISIBLE);
trans.setVisibility(View.VISIBLE);
pb.setVisibility(View.VISIBLE);
try {
      new Thread(new Runnable() {
        public void run() {
            // a potentially time consuming task
            while(!errflag) {
                ftp = new Ftp();
                String result = ftp.execute("hi").get();
                if(result.equals("Finished"))
                    break;
            }
        }
       }).start();

    } catch(Exception e){
        e.printStackTrace();
    }
}

答案 3 :(得分:0)

请尝试仅在主线程中运行以下命令,看看是否有帮助。

ip.setVisibility(View.INVISIBLE);
portt.setVisibility(View.INVISIBLE);
conn.setVisibility(View.INVISIBLE);
trans.setVisibility(View.VISIBLE);
pb.setVisibility(View.VISIBLE);