1

サーバーに(を介して)接続するAndroidアプリを作成しようとしてSocketいますが、別のスレッドで実行する必要があると思います。ただし、明らかに、別のスレッドから Android UI にアクセスしたり、変更したりすることはできません。私は何をすべきか?

package me.nrubin29.quiz.student;

import android.app.Activity;
import android.widget.Toast;

import java.io.EOFException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Connection {

    private Socket socket;
    private Thread reader;
    private ObjectInputStream inputStream;
    private ObjectOutputStream outputStream;

    public void initConnection(final Activity activity, final String ip, final String port, final String name) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    Toast.makeText(activity.getApplicationContext(), "Starting connection to " + ip + ":" + Integer.parseInt(port), Toast.LENGTH_SHORT).show();

                    socket = new Socket(ip, Integer.parseInt(port));

                    Toast.makeText(activity.getApplicationContext(), "Connected!", Toast.LENGTH_SHORT).show();

                    outputStream = new ObjectOutputStream(socket.getOutputStream());

                    inputStream = new ObjectInputStream(socket.getInputStream());

                    outputStream.writeObject(name);

                    reader = new Thread(new Runnable() {
                        public void run() {
                            while (true) {
                                try {
                                    Object in = inputStream.readObject();
                                    System.out.println(in);
                                }
                                catch (EOFException e) { Toast.makeText(activity.getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); }
                                catch (Exception e) { e.printStackTrace(); }
                            }
                        }
                    });

                    reader.start();
                }
                catch (Exception e) { e.printStackTrace(); }
            }
        }).start();
    }
}
4

4 に答える 4

0

Android で「マルチスレッド化」を処理するにはいくつかの方法があり、必要に応じてアプローチが異なる場合があります。

単純な Java スレッドを使用し、アクティビティへの参照があるとします (提供されている例のように)。 activity.runOnUiThread(Runnable r) を呼び出して、UI を更新するランナブルを渡すだけです。これにより、実際にはランナブルが他の UI イベント (アニメーションなど) の後に実行されます。

これに対処するもう 1 つの簡単な方法は、Activity で「final Handler handler = new Handler()」を呼び出し、このハンドラ参照をスレッドに渡すことです。Handler は、アクティビティの UI スレッド (そこから呼び出された場合) にバインドされる特別なオブジェクトの 1 つであり、バックグラウンド スレッドから UI スレッドにランナブルをポストするメソッドも提供できます。

さらに別の方法は、AsyncTask を使用することです。これは、処理の前に ui スレッドで何かを行う機能を提供する単純なオブジェクトであり (読み込みダイアログを表示するなど)、バックグラウンド スレッドで処理を行い、次に何かを行います。バックグラウンド処理の結果をメイン スレッドに戻します。このサイクルは onPreExecute() -> doInBackground() -> onPostExecute() です。

必要に応じて、他のアプローチもあります。

いくつかの点に注意してください:

アクティビティには明確に定義されたライフ サイクルがあり、バックグラウンド処理が発生する前に終了する場合もあれば、終了しない場合もあります。UI を更新しようとしたときにアクティビティがまだ生きているかどうかを確認するための何らかのメカニズムを定義する必要がある場合もあれば、そうでない場合もあります。そうしないと、問題が発生します。AsyncTask には、アクティビティ onDestroy() に基づいてキャンセルを受け入れるための非常に便利な機能があります。これは、アクティビティ onDestroy() の AsyncTask で「キャンセル」を呼び出し、AsyncTask からこのキャンセルを確認するだけです。

バックグラウンド スレッドは、使用状況に応じて、実際に必要以上のものへの強力な参照を保持する場合と保持しない場合があります。アクティビティからバックグラウンド スレッドまたは AsyncTask に参照を渡す場合は、Java の WeakReference を参照することをお勧めします。

複数の同時 AsyncTask を起動するスレッド条件は、プラットフォームのバージョンに応じて、非同期または同期処理で終了する場合と終了しない場合があります。

于 2013-09-23T20:10:01.170 に答える
0

UI スレッドを変更するには多くの方法がありますが、そのうちの 1 つはメッセージをハンドラーにプッシュすることです。

 Handler handler = new Handler(){

  public void handleMessage( Message msg ){
     //Perform yor UI Modification
  }

}

handler.sendMessage( msg );
于 2013-09-23T20:13:25.830 に答える
0

runOnUiThread渡しているを呼び出しActivityます。これにより、メッセージが UI スレッドにポストされます。実行に時間がかかりすぎるメッセージを UI スレッドに投稿しないでください。そうしないと、アプリがロックされ、Android がユーザーに強制的に閉じるように求めます。つまり、ネットワーク接続や重い計算はありません。

例:

activity.runOnUiThread(new Runnable()
{
    @Override
    public void run() 
    { 
          // Your UI stuff here
    }
});
于 2013-09-23T19:51:54.170 に答える