0

ケース:アクティビティにボタンとリストビューがあります。ボタンをクリックすると、進行状況バーを更新する新しいスレッドを開始するクリック リスナーを追加しました。仕事が完了した後、つまりプログレスバーが 100% 完了したら、リストビューを更新したいと思います。

final OnClickListener mStartScan = new OnClickListener() {

    @Override
    public void onClick(View v) {

        // prepare for a progress bar dialog
        progressBar = new ProgressDialog(v.getContext());
        progressBar.setCancelable(false);
        progressBar.setMessage(getString(R.string.text_scanning_inbox));
        progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressBar.setProgress(0);
        progressBar.setMax(totalSms);
        progressBar.show();

        progressBarStatus = 0;

        Thread progressThread = new Thread(new Runnable() {
            public void run() {
                while (progressBarStatus < totalSms) {

                    // process some tasks
                    progressBarStatus = someStuff();

                    // Update the progress bar
                    progressBarHandler.post(new Runnable() {
                        public void run() {
                            progressBar.setProgress(progressBarStatus);
                        }
                    });
                }

                if (progressBarStatus >= done) {

                    // sleep 1 seconds, so that you can see the 100%
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    // close the progress bar dialog
                    progressBar.dismiss();

                    // this method updates the list
                    populateList();
                }
            }
        });
        progressThread.start();

//          try {
//              progressThread.join();
//          } catch (InterruptedException e) {
//              // TODO Auto-generated catch block
//              e.printStackTrace();
//          } finally {
//              populateList();
//          }           
        }
};

問題:タスクが完了してプログレス バーを閉じた後にリストビューを更新すると、ビューが作成されたスレッドからのみビューを更新できるという例外が発生します。

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

他に試したこと:プログレスバーを実行しているスレッドが完了するのを待ってから、メインスレッドからリストビューを更新しようとしました。

try {
    progressThread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    populateList();
}

ただし、これは機能しません。プログレスバーはまったく表示されません。

4

3 に答える 3

1

私はこれを使用しました:

private ProgressDialog progressBar;

class MyTask extends AsyncTask<String, Void, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progressBar = new ProgressDialog(getApplicationContext());
        progressBar.setMessage("please, waiting ...");
        progressBar.setCancelable(false);
        progressBar.show();

    }

    @Override
    protected String doInBackground(String... params) {

        try {
            // get info and set them in my model ...

        } catch (Exception e) {
            e.printStackTrace();
        }

        return params[0];
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        if (null != progressBar && progressBar.isShowing()) {
            progressBar.dismiss();
        }

        // do work in UI and set info adapter and refresh list ...
        populateList();
                    myListView.invalidateViews();
    }
}

詳細については、http: //developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged%28%29を参照してください。

于 2013-06-16T07:50:40.227 に答える
1

ビュー階層を作成した元のスレッドのみがそのビューにアクセスできます。

ここで、元のスレッドは ui スレッドを指します。不可能なスレッド内で ui を更新しようとしています。

バック グラウンド スレッドから ui を更新することはできません。runOnUiThread を使用できます。

 runOnUiThread(new Runnable() //run on ui threa
  {
      public void run() 
      { 

      }
   }); 

asynctask を使用することをお勧めします

この目的には、asynctask を使用します。onPreExecute()、onPostExecute() は ui スレッドで呼び出され、同じものを使用して ui を更新できます。doInbackground() でバックグラウンド計算を行うことができます

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

The 4 steps という見出しの下のトピックを確認してください。

    class TheTask extends AsyncTask<Void,Void,Void>
    {

@Override
protected Void doInBackground(Void... params) {
    // TODO Auto-generated method stub
            // background computation and publish progress      
    return null;
}
    @Override
protected void onProgressUpdate(Void... values) {
    // TODO Auto-generated method stub
    super.onProgressUpdate(values);
           // update progress bar
}

@Override
protected void onPostExecute(Void result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
            // cancel the progress bar
}

@Override
protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
             //display progress bar    
}

}

UI スレッドに asynctask をロードする

     new TheTask().execute(). 
于 2013-06-16T07:53:07.033 に答える
0

表示されるエラーは、セカンダリ スレッドで UI コンポーネントを変更しようとしていることが原因です。Android でスレッドを使用する方法の詳細については、こちらをお読みください。

メソッドを使用してActivityメソッドrunOnUIThread()を呼び出すpopulateList()か、UI (メイン) スレッドで更新を行うものを呼び出すことができます。上記のドキュメントを読むと、これについて詳しく知ることができます。

于 2013-06-16T07:43:02.237 に答える