アンドロイド:アプリケーション+スレッドのハンドラの非同期処理

オリジナルの消失、このレコードを行うには心配、ありがとう

https://www.cnblogs.com/net168/p/4075126.html

 

序文

  長い時間前、私は聞いて、別の仮想マシンのDalvikプロセスで別々に実行されますが、開始するには、各仮想マシンのプライマリUIスレッド(メインスレッド)を実行すると、なぜすべてのアンドロイドアプリ私の代わりにそれのメインスレッドAIやBI、メインスレッドのメインUIスレッドと呼ばれますか?それはすべてのイベントとUI関連に対処する必要があるため、AndroidのUIシステムは、シングルスレッドモデルを使用しているため、多くの手を保持している子スレッドがメインUIを助けるために意識の光を作れば、それだけで彼らのメインスレッドのUIのUI操作で行うことができ、ああ〜Androidのシステムが間違ってレポートされますスレッドの更新のUIインターフェイスは、その後、ごめんなさい。下品なポイントはこれですと言う:我々は唯一のメインスレッドでUIのUIインターフェースを荒廃することができますが、他のスレッドは、その後、被告は女性のドライ滴をGongsuiます。

  だから今の質問です!そう、最近の火災の掘削機を考えると、私はこの質問をし続けて申し訳ありません。そのような時間のかかる操作ショベルなどはぁ〜ネットワーク運用多少時間がかかるように、私たちは、ピットを掘るために掘削機を使用してファイルをダウンロードしたときのように、掘削機の運転手は仕事を見つけるためにピットボスフィードバックを掘ったとき完全に、私たちは自然に良いが、すぐにハード画面は、彼らは**それをaviファイルどのように心配して見たいものを知っているユーザーを、強制する前に待機するように言われたファイルをダウンロードしたい、しかし、あなたは神経を掘る際に、その隣にあなたを見て上司を呼び出すために?ボスダウン数千万人のための毎分はそれを行うには - これはメインスレッドの原因の死カードインタフェースをブロックするように忙しいまあ同様に、ネットワーク運用のために、我々は確かに、メインUIスレッドでネットワークを動作させることができない、また、ANRを引き起こす可能性があります(アプリケーション応答なし)。私たちは、時間のかかる操作は、サブスレッドに配置するように、子スレッドがUIインターフェイスは、完了時間のかかる操作に応答通知するまでファイルは、読み込み、ダウンロードを提出する必要があります。

メインUIスレッドで操作を消費しないでください。

  あなたが何もしないし、メインUIスレッドでファイルをダウンロードしてください場合は、時間のかかる操作は、大容量のファイルなどをロードします。次のコード:

プライベートボタンBTN;
 // ライフサイクルのonCreateこのような方法は、メインUIスレッドできるようにすることである
@Override
 保護 ボイドのonCreate(バンドルsavedInstanceState){
  スーパー.onCreate(savedInstanceState)を、
  setContentView(R.layout.activity_main); 
        
  BTN = (ボタン)findViewById(R.id.btn); 
        
  btn.setOnClickListener(新新OnClickListenerに(){ 
    @Override 
    公共 のボイドのonClick(ビューV){ 
      DOWNLOAD(); //は、メインUIスレッドをダウンロードする機能を呼び出す
    } 
  }); 
} 
    
プライベート 無効DOWNLOAD(){
  試み{ 
    のThread.sleep(10000); // スリープ10秒間、操作を消費するアナログネットワーク・ファイル・ダウンロード 
  } キャッチ(InterruptedExceptionあるE){ 
    e.printStackTrace(); 
  } 
}

あなたは)ボタンが押されたことを示す、暗いの操作をダウンロードする10秒:(シミュレーションボタンメインインターフェイスカードを見つけます

あなたが実行すると、あなたの手にも数回クリックするインターフェースかかわらず、すべての権利〜Androiシステムはすぐにあなたに贈り物ANRああ、ともない998元ええが送信されます、制御不能です!

概要A:メインUIスレッドに時間のかかる操作になる、あなたがメインUIスレッド、メインUIは、ライフサイクル・アプローチの内側などのアクティビティ、サービスを実行しているメインスレッドが何であるかを問う、そうなのonCreateにライフサイクルアプローチを行う可能性がありますしないでください( )これらの偉大なイベントをダウンロードします。時間のかかる操作のために、我々は新しい子スレッドを作成し、彼の処分ではなく、それに注意を払う必要があるはずです。

サブスレッドでUIインターフェイスを更新しないでください

  私たちは子スレッドにあるように、ファイルをダウンロードしてくださいと言っているので、以下のように、我々は、少し内側に行われた操作にダウンロードするための新しいサブスレッドを作成します。

保護された ボイドのonCreate(バンドルsavedInstanceState){
  スーパー.onCreate(savedInstanceState)。
  setContentView(R.layout.activity_main)。
        
  BTN = (ボタン)findViewById(R.id.btn)。
  テキスト = (のTextView)findViewById(R.id.text)。
        
  btn.setOnClickListener(新しいOnClickListener(){ 
    @Override 
    公共 のボイドのonClick(ビューV){
      新しいスレッド(){ 
        @Override 
        公共 ボイドラン(){
          // 在子线程中进行下载操作
          してみてください{ 
            のThread.sleep( 10000); //10秒間、操作を消費するアナログスリープ 
          } キャッチ(InterruptedExceptionあるE){ 
            ; e.printStackTrace()
          } 
          text.setText( "ダウンロードが完了する"); // 設定のTextView、ダウンロード完了通知UIインターフェース
        } 
      } .start(); 
    } 
  }); 
}

10秒後、あなたは完全に「ダウンロードが完了すると、」UIインターフェイスに表示感じられるでしょうか?一般的に、このシステムの出現は、Androi一貫したスタイルと一致しています

次のようにして、ログが与えられています

実際には、英語の廃材の弟ですが、それは漠然とした私に言った:これはコールのみ行うメインスレッドでUIを更新することができないのですか?Kingsoftの翻訳にオフに見て、信じてはいけません。

概要A:サブスレッドでUIインターフェイスを更新しないでください、これはAndroidのシステム・エラーのため、アプリケーションが終了しクラッシュつながります。これらのサブあなたは、シングルスレッドモード、我々は唯一のUIインターフェイス関連の更新プログラムへのメインスレッドのUIインターフェースUIを通じて、ライン作業を横切らないことができ、あなたは覚えておく必要がある〜UIインターフェイスは、メインUIスレッドの妻であります誰でも移動について考えていないスレッド!

非同期処理を使用してスレッド+ハンドラ

  質問があるので、メインスレッドは、今、私たちは(そのようなファイルのダウンロードなど)時間のかかる操作を実行する必要があるときに実行することができない、私たちは仕事にサブスレッドの実行を終了することができないUIインターフェースでユーザーに通知する必要があります。これは、トリッキーなホットポテトのようですが、幸いGoogleは苦痛で私たちにハンドラを保存し、メインスレッドがメッセージを送信するために子スレッドに耳を傾けるものを作ることができると私たちを提供し、原則ハンドラの実現として、また戻ってきます記事の詳細、そして今私達はちょうど最初のハンドラの使用状況を理解する必要があります。

private Button btn;
private TextView text;
    
private Handler handler = new Handler(){
  private int process = 0;
  @Override
  public void handleMessage(Message msg) {
    switch(msg.what){
    case 0://更细下载进度
      process += 1;
      text.setText("下载" + process + "%");//在主线程中更新UI界面
      break;
    case 1://提示下载完成
      text.setText("下载完成");//在主线程中更新UI界面
      break;
    default:
      break;
    }
  }
};
//onCreate之类的生命周期的方法就是允许在UI主线程中
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
        
  btn = (Button) findViewById(R.id.btn);
  text = (TextView) findViewById(R.id.text);
        
  btn.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    new Thread(){
      @Override
      public void run() {
        //在子线程中进行下载操作
        for(int i = 0; i < 100; i++){
          try {
            Thread.sleep(200);//休眠0.2秒,模拟耗时操作
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          handler.sendEmptyMessage(0);//发送消息到handler,通知下载进度
        }
        handler.sendEmptyMessage(1);//发送消失到handler,通知主线程下载完成
        }
      }.start();
    }
  });
}

这里来解释一下Handler的使用方法:

1、我们为了不阻塞主线程,将下载任务通过子线程来执行。

new Thread(){
  @Override
  public void run() {
    //在子线程中进行下载操作
    for(int i = 0; i < 100; i++){
      try {
        Thread.sleep(200);//休眠0.2秒,模拟耗时操作
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      handler.sendEmptyMessage(0);//发送消息到handler,通知下载进度
    }
    handler.sendEmptyMessage(1);//发送消失到handler,通知主线程下载完成
  }
}.start();

2、当子线程需要跟主线程交流时,也就是当子线程要跟UI主线程说:亲,偶下载文件到80%了或者偶已经把文件下载完成了!执行这句代码

handler.sendEmptyMessage(1);//发送消失到handler,通知主线程下载完成

3、当发送空消息之后,在Handler将会收到子线程发来的消息,触发回调方法handlerMessage(),我们就在这里对UI界面进行更新,这个回调方法是运行在UI主线程的

@Override
public void handleMessage(Message msg) {
  switch(msg.what){
  case 0://更细下载进度
    process += 1;
    text.setText("下载" + process + "%");//在主线程中更新UI界面
    break;
  case 1://提示下载完成
    text.setText("下载完成");//在主线程中更新UI界面
    break;
  default:
    break;
  }
}

4、最后,UI界面更新成功!(图嘛,我这里就不上了。。。。)

小结一个:对于比较耗时间的任务,我们一般需要放在子线程中执行;当子线程更新UI界面时,子线程可以通过Handler来通知主线程更新,一般通过发送消息来触发handlerMessage()这个回调方法来执行UI界面的更新。

进一步简略de操作:handler.post方法和view.post方法

  但是如果你觉得每次都要重写handlerMessage()比较麻烦,我们完全可以用更加简略的方法来解决我们的需求,就是用handler中的post方法。代码如下

 

new Thread(){
  @Override
  public void run() {
    //在子线程中进行下载操作
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    handler.post(new Runnable() {
      @Override
      public void run() {
        text.setText("下载完成");
      }
    });//发送消失到handler,通知主线程下载完成
  }
}.start();

 

这样处理的话我们就可以不用重写handlerMessage()方法了,适合子线程与主线程进行较为单一的交流。但在这里我们要强调的一点的是,post里面的Runnable还是在UI主线程中运行的,而不会另外开启线程运行,千万不要在Runnable的run()里面进行耗时任务,不然到时又ANR了可别找我哦。。 如果你有时候连handler都不想搞,还可以这样写代码滴。 我们只需要把handler换成View组件进行post,更新任务自然会加载到UI主线程中进行处理。

text.post(new Runnable() {
  @Override
  public void run() {
    text.setText("下载完成");
  }
});//发送消失到handler,通知主线程下载完成

至于Handler机制以及这两种post的原理,我将会在后面的博客文章中专题介绍,这里只提供一个使用方法而已。

 

おすすめ

転載: www.cnblogs.com/zonglonglong/p/11258399.html