0

更新されたメッセージのために毎秒サーバーをプルするコードを書き込もうとしています。その後、メッセージはテキストビューに表示されます。テキストビューのテキストを変更しないと、正常に実行されます。スレッドのテキストビューを変更しようとするとクラッシュします。スレッド上で変更しない場合は正常に動作します。

スレッドがメインスレッドのメモリにアクセスできないと思いますか?インターネット経由でロードしたばかりのテキストをビューに設定するにはどうすればよいですか?

以下のコードには、スリープでエンドレスループを実行するスレッドがあります。SendMessageというメソッドを呼び出します。メッセージの送信はインターネット経由でテキストで読み込まれ、最後にビューを更新しようとします。これが発生すると、例外が発生します。

コード:

public class cChat extends cBase  implements OnClickListener {
    /** Called when the activity is first created. */
      TextView mUsers; 
      TextView mComments; 
      int i=0;

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.chat);

            mUsers=( TextView) findViewById(R.id.viewusers);;
            mComments=( TextView) findViewById(R.id.viewchats);;

          Thread thread = new Thread()
          {
              @Override
              public void run() {
                  try {
                      int t=0;
                      while(true) 
                      {
                          SendMessage();
                          sleep(1000*5);
                          t++;
                      }
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          };

          thread.start();

        }


       public void onClick(View v) {


           } // end function



        // send a uypdate message to chat server 
        // return reply in string
        void SendMessage()
        {


            try {


            URL url = new URL("http://50.63.66.138:1044/update");
               System.out.println("make connection");

               URLConnection conn = url.openConnection();
               // set timeouts to 5 seconds
               conn.setConnectTimeout(1000*5);
               conn.setReadTimeout(5*1000);
               conn.setDoOutput(true);
               BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));


            //   String line;
               String strUsers=new String("");
               String strComments=new String("");
               String line=new String();
               int state=0;
               while ((line= rd.readLine()  ) != null) {
                 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:
                       if ( line.contains("END COMMENTS"))
                             state=0;
                       else {
                       strComments+=line;
                       strComments+="\n";
                       }
                       break;
                 } // end switch   
               } // end loop

      // 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());
           }

        } // end methed
}
4

5 に答える 5

3

runOnUiThread を次のように使用します

 YOUR_CURRENT_ACTIVITY.this.runOnUiThread(new Runnable() {

         @Override
         public void run() {
         // the next line will cause a exception
           mUsers.setText(strUsers);
           mComments.setText(strComments);
            //....YOUR UI ELEMENTS
         }
        });

編集: ドキュメントrunOnUiThreadを参照してください

于 2012-06-20T18:41:43.023 に答える
0

ハンドラーを使用して、タスク(Runnables)をUI/メインスレッドに投稿できます。

private Handler handler = new Handler();

//...

Thread thread = new Thread()
{
@Override
public void run() {
    try {
        int t=0;
        while(true) 
        {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    SendMessage();
                }
            });

            sleep(1000*5);
            t++;
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
};
于 2012-06-20T18:47:55.083 に答える
0

UI ウィジェットの作成に使用したスレッド (UI スレッド) とは異なるスレッドから UI ウィジェットにアクセスすることはできません。しかし、 への参照がある場合は、次のActivityように簡単に実行できます。

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        mUsers.setText(strUsers);
        mComments.setText(strComments);
    }
});

strUsers匿名クラスからアクセスできる必要があります。そのためには、次のように簡単に実行できます。

final String finalUseres = strUsers;

finalUsers内で使用してrun()ください。

于 2012-06-20T18:44:37.680 に答える
0
the Andoid UI toolkit is not thread-safe. So, you  
must not manipulate your UI from a worker thread    

この問題を解決するために、Android には、他のスレッドから UI スレッドにアクセスする方法がいくつか用意されています。役立つメソッドのリストを次に示します。

AsyncTaskも使用できます。

Android のプロセスとスレッドに関するこのチュートリアルを参照してください。

于 2012-06-20T18:45:15.453 に答える
0

Serviceを使用して、サーバーにデータを継続的にプル/送信してみてください。これにより、UI スレッドの負荷が軽減されます。

于 2012-06-20T18:48:24.843 に答える