【问题标题】:Unable to update EditText from AsyncTask and an infinite loop无法从 AsyncTask 和无限循环更新 EditText
【发布时间】:2016-03-27 08:57:44
【问题描述】:

我有以下问题。在主线程上,我有一个EditText 字段,我有一个AsyncTask,它无限地侦听套接字以获取传入消息。在循环中(位于doInBackground())我试图调用onProgressUpdate()并将其传递给一个字符串,我希望当oPU()接收到字符串时将其显示在位于主线程的EditText上.

  public class ClientSide extends AsyncTask<String, String, String>{
  public EditText field = (EditText) findViewById(R.id.bar1);
  ...}

第一个问题是findViewById(R.id.bar1) 上的它说无法解析符号。什么可能导致它,我该如何解决它。 第二个问题是循环。问题是我不想通过主线程定期创建新的AsyncTask 对象,因为在我的情况下,这意味着每次对象是 .execute()-ed 时都创建一个套接字并绑定到它。请建议我一种重新组织代码的方法,以便使解决方案更加优雅。我知道AsyncTasks 是针对不长应用程序的短流程,所以我知道我当前的解决方案(带有循环)是一个正在分解的胡萝卜(也就是坏的)。 再来一次: 1、如何让findViewById()真正匹配EditText的UI元素? 2. 当应用程序需要在后台执行其消息侦听器时,如何重新组织我的代码以便不创建套接字?

您也可以看到 Async.. doInBackground:

protected String doInBackground(String... params){

    final String SERVER_HOSTNAME = "hereGoesMyIP";
    final int SERVER_PORT = 2002;
    BufferedReader mSocketReader;
    PrintWriter mSocketWriter;
    final String TAG = ClientSide.class.getSimpleName();
    String outputln = "Me. Android";


    try {
        //Initialization of the socket, socket reader and writer.
        Socket socket = new Socket(SERVER_HOSTNAME, SERVER_PORT);
        mSocketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        mSocketWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        System.out.println("Connected to server " + SERVER_HOSTNAME + ":" + SERVER_PORT);


        //An infinite loop which checks for incoming messages.
        while(true){
            String inMsg="";
            String aMessage = "";

            //Reads from the socket
            if((inMsg=mSocketReader.readLine())!=null && socket.isConnected()){
                publishProgress(inMsg);
            }

            Thread.sleep(500);//still requres try - catch?
        }


    } catch (IOException ioe) {
        System.err.println("Cannot connect to " + SERVER_HOSTNAME + ":" + SERVER_PORT);
        ioe.printStackTrace();

    }

    return null;
}

【问题讨论】:

    标签: java android sockets loops android-asynctask


    【解决方案1】:

    1)findViewByid() 是 Activity 类中可用的方法。它在 AsyncTask 类中不可用。因此,像这样将您的视图传递给 AsyncTask

     private Context mContext;
    private View yourView;
    
    
        public Clientside(Context context, View rootView){
            this.mContext=context;
            this.yourView=rootView;
        }
    

    然后你可以这样访问它

    EditText editText = yourView.findViewById(R.id.edit_text);
    

    请记住,您无法从后台线程更新视图,因此请使用 progressupdate()postExecute() 方法更新在主线程上运行的 EditText。

    @Override
    protected void onPostExecute(String result) {
    
    }
    
    
      View rootView = findViewById(android.R.id.content).getRootView();//This will return you the rootView
    
    
    
    ClientSide cs = new ClientSide(getApplicationContext(),rootView);//do this in your mainactivity
    

    getApplicationContext() 将返回您所在的上下文。

    谢谢。我希望这会有所帮助。

    【讨论】:

    • 非常感谢您提供如此详细的答案。我现在正在测试您的解决方案。如果您有任何关于 2) 的信息,我会很高兴...阅读它。再次感谢你。我希望检查你的答案是最好的。请给我 1-2 分钟的时间来运行它...
    • 2) 我能理解你的问题
    • 你能解释一下你的第二个问题吗?
    • 它是关于如何只创建一次套接字并将其传递给 AsyncTask。这种方式在异步中我将只做监听器,我会定期从主线程调用异步线程,因此我将避免异步中的无限循环。目前该程序做相反的事情 - 调用 Async 一次,然后创建一个套接字一次(好的),但有一个无限循环,我认为这是最糟糕的解决方案。我知道异步是针对短流程而不是针对应用程序的,从这个角度来看是“最糟糕的”
    • 如果这就是你想要的。然后在你的 mainThread 中创建一个套接字,并将它传递给你的构造函数,就像我们对视图所做的那样。这可能会解决您的问题。谢谢你
    【解决方案2】:

    我相信要停止这个问题,你必须刷新 onProgressUpdate 内的 EditText

    例如:

    protected void onProgressUpdate(String newText) {
      field.setText(newText);
      field.invalidate();  
    }
    

    并在主线程外部声明字段变量..而不是在客户端类内部..

    这个 onProgressUpdate(..) 在你的 ClientSide..

    【讨论】:

    • field 也是cannot resolve symbol...这行不通。
    • @KDX2 是的,对此感到抱歉..我忘了看到..jois 创建 view.findViewById 的方式更好我相信..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多