2

私は現在、個人的な使用のためだけにAndroidアプリに取り組んでいます。アプリは、TCP ソケットによってサーバーと通信します。ユーザーが入力を行った場合は、すぐに送信する必要があります。また、UI に表示する必要があるサーバーからのメッセージがいつでも発生する可能性があります。すべてのネットワーキングについて、私はバックグラウンド スレッドを念頭に置いています。

ユーザー入力時に UI からネットワーク スレッドにメッセージを渡す必要があるため、任意の時点でネットワーク スレッドから UI にメッセージを渡す必要があるため、質問は次のとおりです。メッセージを渡すにはどうすればよいですか? 私はすでに Handler クラスについて 3 時間読んでいましたが、何も理解できませんでした。ハンドラーはどのように機能しますか? それをうまくスムーズに実行するにはどうすればよいでしょうか。必ずしも実装の詳細ではなく、この目標を達成するための戦略をもっと探しています。

よろしくお願いします!

4

3 に答える 3

1

こんな場合に使えますAsyncTask。UI スレッドで呼び出して、onPostExecute でメッセージに対してやりたいことを実行できます。そこですべての汚いネットワーク作業を行うよりも、はるかにクリーンなアプローチです。

于 2012-04-16T19:36:14.023 に答える
1

最初に、私はこれを自分で学んでいると言いますが、この正確なセットアップをプロトタイプで動作させることができました. Android でより適切に動作するように変更する必要があるものを見つけた場合は、ぜひお知らせください。

2 つ目は、実際に機能するコードを作成できるように、空のメッセージを使用していることです。メッセージ オブジェクトの作成は簡単だと思います。

パート 1 - UI からネットワーク スレッドへ

私が見た限り、Handler は必要な答えですが、それが全体像ではありません。Looper に関する Deucalion のコメントは、次に注目する必要がある場所です。

http://developer.android.com/reference/android/os/Looper.html

class LooperThread extends Thread {
  public Handler mHandler;

  public void run() {
      Looper.prepare();

      mHandler = new Handler() {
          public void handleMessage(Message msg) {
              // process incoming messages here
          }
      };

      Looper.loop();
  }
}

このセットアップは最初は直感に反します。メソッド内でLooper.prepare()との呼び出しの間に Handler オブジェクトを作成する必要があります。私は舞台裏の魔法を知りません。うさぎの穴をそこまで掘り下げる機会はありませんでした。Looper.loop()run()

重要な注意: このサンプルは、匿名の Handler() が作成されていることを示しています。独自のクラスで Handler をサブクラス化し、そのインスタンスを使用することを強くお勧めします。これは単に再利用性の問題であり、多くのネットワーク コードは最終的に同じになります。

したがって、名前LooperThreadNetworkThread、または好きなものに変更し、接続コードをrun()メソッド内に配置しますが、ブロックの外側に配置しLooper.prepare() / Looper.loop()ます (魔法がどのように機能するかわかりません。中に入れないでください)。

// process incoming messages here

次のようになります。

switch(msg.what)
{
    case 1:
        break;
    default:
        break
}

LooperThread の例にはpublic Handler mHandler;ありますが、ハンドラーをプライベートにして、それを返すメソッドを作成することを好みます。これは、ネットワーク接続が確立されるまでハンドラーにアクセスできないようにするためです。連絡なし、メッセージとは何の関係もありません。

したがって、アクティビティ コードのどこかにNetworkThreadオブジェクトを作成して実行し、そこから Handler を取得します。

NetworkThread network = new NetworkThread();
new Thread(network).run();
//Handler networkHandler = network.handler;
Handler networkHandler = network.getHandler();

次に、必要に応じてそのハンドラーにメッセージを送信します。

networkHandler.sendEmptyMessage(1);

パート 2 - UI へのネットワーク スレッド

これを処理するには、いくつかの方法があります。Activity クラス内にハンドラーを作成できます。すべてのアクティビティにはすでに Looper が設定されているため、Looper.prepare と Looper.loop を呼び出すと問題が発生するようです。

私のコードでは、onCreate()メソッドでハンドラーを作成し、それをNetworkThreadオブジェクトに渡します。この Handler を作成するためのより良い場所があるかもしれません。アプリケーションが一時停止され、後でonResume()またはonRestart()

public NetworkThread(Handler mainHandler)
{
    this.mainHandler = mainHandler;
}

次に、UI にメッセージを送信する必要がある他の場所:

this.mainHandler.sendEmptyMessage(1);

私がこの方法を好むのは、実際の作業を行う Handler コードが (匿名の Handler オブジェクトを使用して) メッセージに実際に応答するクラスに存在するか、同じパッケージ内にある可能性のある Handler サブクラスに存在するためです。

Activityネットワーク スレッドにまたはViewをその呼び出しから渡すこともできますがrunOnUIThread(Runnable)、それには Runnable を渡す必要があります。そのため、UI で動作することを意図したコードは、Networking クラスで記述または参照されています。


アップデート

これには Service を使用することもできます。上記の方法は、Activity と Networking の寿命が同じ場合に機能します。アクティビティがアクティブな間だけネットワーク接続が必要な場合。

たとえば、音楽ストリーミング アプリで、Activity の寿命を超えてネットワーク接続が必要な場合は、Service を使用することをお勧めします。これは、特にあなたが質問を探していたものではないようです。

于 2012-11-09T04:17:15.290 に答える
1

http://developer.android.com/reference/android/os/AsyncTask.htmlこれを使用してください 私もハンドラーで多くの問題を抱えていましたが、非同期タスクは面倒な作業をすべて処理します。UI を更新するには、必ず onPreexecute() と onPostExecute() を使用してください。お役に立てれば。

于 2012-04-16T19:34:52.017 に答える