3

ここで同様の質問をするいくつかの質問を見てきましたが、適切な回答はまだ見ていません。多くの人がスレッドから UI を更新する方法を尋ねてきましたが、ほとんどの場合、UI と同じクラスに属しています。

私がやろうとしているのは、別のクラスで作成されたスレッドから UI を更新することです。async、handlers、runnable などのすべての提案を見てきましたが、それらを別々のクラスに実装するのに本当に苦労しています。

UI クラスを最小限に抑え、ユーザーがボタンを押したときなど、GUI との対話のみを処理しようとしています。ここで、Bluetooth デバイスに接続する新しいクラスで新しいスレッドを作成しましたが、UI スレッドのボタンを「接続」ボタンから「切断」ボタンに変更したいと考えています (つまり、 Bluetooth ソケットの作成から閉じるまでのボタン)。

これを行う一般的な方法は何ですか?私はこれをすべて間違っていると考えており、すべてを1つのクラスに含める必要がありますか? 「メイン」UI クラスと他のクラス/スレッドとの間で対話する正しい方法は何ですか?

理想的には、他の UI インタラクションを実行できるようにしたいので、UI クラスの外部で他の UI の変更を可能にするソリューションがあれば素晴らしいでしょう!

4

3 に答える 3

8

私がやろうとしているのは、別のクラスで作成されたスレッドから UI を更新することです。async、handlers、runnable などのすべての提案を見てきましたが、それらを別々のクラスに実装するのに本当に苦労しています。

一般的に、あなたの目標のために私はあなたが使用することをお勧めします:

あまりにもトリッキーだとは思いません。絶対違う。一部のクラスの内部クラスとしてではなく、分離されたクラスとして持っている場合はActivity、コンテキスト、ウィジェット、一般的に必要なものを渡すコンストラクターを使用し、正しいメソッドで使用することをお勧めします(UI の更新を可能にします)。を更新しますUI

私はきれいなクラスがあるときが好きなので(UIクラスにはUI実装のみがあり、ロジックは個別に配置されています)、そうしています。

例:

public class TaskExample extends AsyncTask<Void, Integer, Void> {

   private Context c;
   private Button b;

   public TaskExample(Context c, Button b) {
      this.c = c;
      this.b = b;
   }

   protected Void doInBackground(Void... params) {
      // some work
      if (isSomethingConnected) {
         publishProgress(Constants.IS_CONNECTED);
      }
      return null;
   }

   public void onProgressUpdate(Integer... params) {
       switch (params[0]) {
          case Constants.IS_CONNECTED:
             b.setText("Connected");
          break;
          case Constants.ANOTHER_CONSTANT:
             // another work
          break;
       }
   }  
}

使用法:

public class Main extends Activity implements View.OnClickListener {

   private Button b;

   public void onCreate(Bundle b) {
      super.onCreate(b);
      // initialise widgets and set listeners to appropriate widgets
   }

   public void onClick(View v) {
      switch(v.getId()) {
         case R.id.connectBtn:
            startWorker();
         break;
      }
   }

   private void startWorker() {
      TaskExample te = new TaskExample(this, b);
      te.execute();
   }
}
于 2013-02-20T17:34:25.857 に答える
2

いくつかのオプションがあります。変更しているビューにアクセスでき、単に更新を強制する必要がある場合はView.postInvalidate()、任意のスレッドから使​​用できます。ボタンのテキストを変更するなど、より複雑な操作が必要な場合は、コンテキストrunOnUIThreadへのアクセスを必要とする を使用する必要があります。Activityこれは簡単に取得できます。カスタム オブジェクトのコンストラクターのパラメーターとして追加するだけです。このコンテキストでは、次のようなことができます。

activityContext.runOnUiThread(new Runnable(){
    @Override
    public void run() {
        myButton.setText("disconnect");
    }
});
于 2013-02-20T18:02:43.357 に答える
0

メソッドを使用runOnUiThread(Runnable)してメイン スレッドで何かを実行し、ClassName.View.invalidate()それがビューの場合はメソッドを呼び出します。または public、UI の更新を処理する Target クラスでメソッドを作成するだけです。

于 2013-02-20T17:34:04.297 に答える