2017-12-17 5 views
-1

現在、Bluetooth、GPSを使用し、リモートサーバーにデータをアップロードするアプリケーションで作業しています。私はすべてが一緒に働くように一連のイベントとスレッドを起動する単純なボタンを持っています。OnClickの間に複数のTextViewの変更を表示

私は現在TextViewコンポーネントを画面に追加しています。これは、ユーザーに何が起こっているのかをより詳細に示すプロセスです。 GPSは作動していますか?私のBluetoothデバイスは接続されていますか?このプロセスには最大10秒かかることがあるため、バックグラウンドで何が起こっているかについてさらに情報を追加しています。

ただし、自分のボタンをクリックすると、最後の変更のみが表示されます。私はTextViewのコンポーネントがOnclickの後にレンダリングされたとしますか?

例:

@Override 
public void onClick(View view) { 
    textView.setText(R.string.launching_text); 
    // start a thread 
    textView.setText(R.string.start_new_thread); 
    // start another thread 
    textView.setText(R.string.almost_there); 
    // start last thread 
    textView.setText(R.string.done); 
} 

は、このプロセスは約10秒を取って想像してみてください。アプリが「フリーズ」しているように見えますが、変更はOnClickが終了するまで表示されません。

OnClickイベント中にリアルタイムで私の情報を表示するにはどうすればよいですか?おそらくもっと良い方法はありますか?非同期的にTextViewの変更をプッシュするいくつかの種類の方法を行うことは可能ですか?

+1

別のスレッドを使用してtextviews – Zoe

+0

を設定し、そのスレッド内の 'runOnUiThread'を使用するが、だからあなたは、いくつかの秒後、ユーザーに異なるメッセージを表示するようにしたいですか? –

+1

Rxjavaのzip演算子を使用し、これらの観測値を組み合わせることで、同時に応答をuiスレッドに表示し、その間に進行状況を表示できます。 [here](http://reactivex.io/documentation/operators/zip.html) – Debdeep

答えて

1

私はまず、this Android Performance Patterns videoをチェックして、あなたの処分でいくつかのオプションを確認することをお勧めします。また、ライフサイクル環境(たとえばActivitiesFragments)でマルチスレッドを実行しないようお勧めします。

onClickの例では、R.string.doneは、最初のスレッドが処理を完了する前に表示される可能性があります。私はそれが本当にあなたが望むものではないと仮定しています。

あなたが取り組んでいる問題、使用しているツール、またはあなたがフォローしているアーキテクチャについては何も知らないので、ここにはがあります。少し一般的なやり方です。 onClick実装の各Threadには、ソートのステータスがあります。あなたは、単純な抽象化とコードでこれを表すことができます:

class Holder { 
    @StringRes int status; 
    Runnable runnable; 

    Holder(@StringRes int status, @NonNull Runnable runnable) { 
    this.status = status; 
    this.runnable = runnable; 
    } 
} 

お知らせRunnableではなくThreadの使用されています。

あなたも順番に実行しています。あなたが例えば流体、表情豊かなAPIを提供し、シンプルListまたはQueueとコードでこれを表すことができます:

serviceExecutorServiceある
@Override 
public void onClick(View v) { 
    final Runnable runnable = new StatusRunnableBuilder(view) 
    .addStep(R.string.launching_text, launchingRunnable) 
    .addStep(R.string.almost_done, almostDoneRunnable) 
    .withFinalStatus(R.string.finally_done) 
    .build(); 
    service.execute(runnable); 
} 

class StatusRunnableBuilder { 
    private final WeakReference<TextView> viewRef; 
    private final Queue<Holder> queue; 
    @StringRes private int finalStatus; 

    StatusRunnableBuilder(@NonNull TextView view) { 
    viewRef = new WeakReference<>(view); 
    queue = new ArrayDeque<>(); 
    } 

    StatusRunnableBuilder addStep(@StringRes int status, 
           @NonNull Runnable runnable) { 
    queue.add(new Holder(status, runnable)); 
    return this; 
    } 

    StatusRunnableBuilder withFinalStatus(@StringRes int status) { 
    finalStatus = status; 
    return this; 
    } 

    Runnable build() { 
    return new Runnable() { 
     @Override 
     public void run() { 
     for (Holder item: queue) { 
      updateStatus(item.status); 
      item.runnable.run(); 
     } 
     if (finalStatus != 0) { 
      updateStatus(finalStatus); 
     } 
     } 
    }; 
    } 

    private void updateStatus(@StringRes final int status) { 
    final TextView view = viewRef.get(); 
    if (view != null) { 
     view.post(new Runnable() { 
     @Override 
     public void run() { 
      // As this has been posted to a queue, 
      // it could have been processed with some delay, 
      // so there is no guarantee the view is still present. 
      // Let's check again. 
      final TextView v = viewRef.get(); 
      if (v != null) { 
      v.setText(status); 
      } 
     } 
     }); 
    } 
    } 
} 

次に、あなたのonClickは次のようになり任意のライフサイクルイベントを作成/停止することができます。:

@Override 
protected void onStart() { 
    super.onStart(); 
    service = Executors.newSingleThreadExecutor(); 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
    service.shutdownNow(); 
} 
0

RunnableにはHandlerを使用できます。 Handlerは一定の間隔の後にRunnableへの更新をポストします。

Bluetooth接続の場合は、ブロードキャスト受信機にも接続できます。

+0

私は、OnClick内でRunnableを使ってみました。 TextViewは更新されません。 – Tumladhir

+0

TextViewが更新されないとはどういう意味ですか? @Tumladhir – mismanc

0

あなたはAsyncTaskを試すことができます。これは非常にシンプルで、すべてのバックグラウンドスレッドとスレッド間通信を処理します。 EventBusなどのメカを使用してメモリリークを回避するには、いくつかの考慮事項があります。ここで私は非常に有用であることが分かっ記事です:

http://simonvt.net/2014/04/17/asynctask-is-bad-and-you-should-feel-bad/

関連する問題