0

我正在尝试制作一个聊天程序,它将每 2 秒拉一次服务器以获取新的 chts。

起初我只是创建了一个线程并更新了线程上的 ui,它崩溃了。

我添加了一个 runnable,其中 run 方法调用了一个名为 SendMessge 的方法。SendMessage 通过 Internet 获取更新的信息,然后更新 ui。

我以为runnable中的run方法将在我的线程下运行,它似乎在ui线程上运行。

当我在发送消息中的网络代码出现错误时,UI 冻结了。

然后我设置了2个断点。一个在runnable之前,下一个在runnable之后。接下来,我在我的服务器中设置了一个断点,这样网络代码就会冻结。那么在android上第一个断点消失了,然后它在runnable之后进入断点而没有等待我释放服务器上的断点,因此我假设runnable在不同的线程上运行,因为代码没有不要等待,我假设它是 ui 线程。

好吧,如果我有这个权利。在创建可运行文件之前,我的网络代码将在线程中。然后将在其运行方法中更新 ui。当我获得更新ui的新信息时出现问题,我如何将它发送到runnable中的run方法???

我的代码:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.chat);
    strComment=new String("na");
    mUsers=( TextView) findViewById(R.id.viewusers);;
    mComments=( TextView) findViewById(R.id.viewchats);
    mUserChat=( EditText) findViewById(R.id.viewedit);
    mScroll=( ScrollView) findViewById(R.id.scrollcomments);
    mHome=( Button) findViewById(R.id.butHome);
    mHome.setOnClickListener(this);
    mEnter=( Button) findViewById(R.id.butEnter);
    mEnter.setOnClickListener(this);

    Thread thread = new Thread(){
        @Override
        public void run() {
            try {
               int t=0;
               flagEnter=true;
               while(true){
                  handler.post(new Runnable() {
                  // I put a break point here
                      @Override
                      public void run() {
                          SendMessage();
                      }
                  });
                  // I put another break point here, it went right here without waiting for the sendmessage to finish
                  sleep(1000*10);
                  //while(true);
               }
           }catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   };

   thread.start();
}

public void onClick(View v) {
    Intent i;
    switch(v.getId()) {
        case R.id.butEnter:
            Editable e = mUserChat.getText();
            strComment=e.toString();
            flagAdd=true;
            break;
        case R.id.butHome:
            i = new Intent(this, TellaFortuneActivity.class);
            i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(i);    
            break;
    }
} // end function

// send a uypdate message to chat server 
// return reply in string
void SendMessage(){
    //////////////////////////////////
    // handle flags
    String de=new String("");
    String strUsers=new String("");
    String strComments=new String("");
    String comment=new String("NA");

    if (flagHome){
        Intent i;
        i = new Intent(this, TellaFortuneActivity.class);
        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(i);
        return;
    }

    String flag="update";
    if (flagAdd){
        // get new text
        Editable  text=mUserChat.getText();
        comment=text.toString();
        mUserChat.setText("");
        flag="add";
    }

    if (flagEnter)
        flag="enter";

    if (flagExit){
        flag="exit";
        flagHome=true;
    }

    // clear all flags
    try {
        URL url = new URL("http://50.63.66.138:1044/"+flag);
        System.out.println("make connection");
        String data = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode("tedpottel", "UTF-8");
        data += "&" + URLEncoder.encode("comment", "UTF-8") + "=" + URLEncoder.encode( comment, "UTF-8");
        URLConnection conn = url.openConnection();
        // set timeouts to 5 seconds
        conn.setConnectTimeout(1000*5);
        conn.setReadTimeout(5*1000);
        conn.setDoOutput(true);
        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(data);
        wr.flush();
        wr.close();

        //    if (flagAdd==false){

        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line=new String();
        int state=0;

        while ((line= rd.readLine()  ) != null) {
            de=de+line;
            switch(state){
                case 0:
                    if ( line.contains("START USER"))
                        state=1;
                    if ( line.contains("START COMMENTS"))
                        state=2;
                    break;
                case 1:
                    if ( line.contains("END USER"))
                        state=0;
                    else{
                        strUsers+=line;
                        strUsers+="\n";
                    }
                    break;
                case 2:
                    // NOTE: end of comments is end, but......
                    // if we do not read in ALL the dat from server
                    // could cause connection errors
                    if ( line.contains("END COMMENTS"))
                        state=0;
                    else {
                        strComments+=line;
                        strComments+="\n";
                    }
                    break;
                } // end switch   
            } // end loop
            rd.close();
        }   
        // the next line will cause a exception
        // mUsers.setText(strUsers);
        // mComments.setText(strComments);
    } catch (Exception e) {
        i++; // use this to see if it goes here in debugger  
        System.out.println("exception");
        System.out.println(e.getMessage());
    }

    flagAdd=false;
    flagEnter=false;
    flagExit=false;
} // end methed

void Test(){
}
4

1 回答 1

0

尝试使用 AsyncTask 进行线程处理。谷歌最简单的教程。

并确保您不在 UI 线程之外的线程内执行任何 UI 操作。始终为 UI 操作执行 activity.runOnUiThread()。像

// 获取新文本

Editable text = mUserChat.getText();
comment = text.toString();
mUserChat.setText("");

此代码必须在 UI 线程上运行,而不是在您的永恒线程上运行。我从您在线程的 run() 方法中调用的方法中获取了这种平静的代码。

在外螺纹中。您必须进行处理和数据工作。并且 UI 更新必须在 UI 线程上完成,并且要在 UI 线程上运行东西总是使用 activity.runOnUiThread() 方法。

问候, 阿基夫·哈米德

于 2012-06-22T13:35:58.780 回答