1

データのフェッチ中にスピナーのロードを示す単純な関数があります(通常は7秒ほどかかります)

private void load_data(View v)
{
    task_complete = false;
    progressBar = new ProgressDialog(v.getContext());
    progressBar.setCancelable(false);
    progressBar.setMessage("Fetching data ...");
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressBar.show();

    try
    {
        Log.v("thread", "Starting thread");
        new Thread(new Runnable()
        {
            public void run()
            {
                while(!task_complete)
                {
                    fetch_data();
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
                progressBar.dismiss();
            }
        }).start();
        Log.v("thread", "Thread finished successfully");
    }
    catch(Exception e)
    {
        Log.v("thread", "fail "+e.toString());
    }
}

私が抱えている問題は、関数がonClickによって呼び出されることです

load.setOnClickListener(new View.OnClickListener()
{
    public void onClick(View v)
    {
        load_data(v);
        show_data(v); // shows the data on a spinner
    }
});

そして、ロードボタンを2回押すと、エラーが発生します。私のログは表示されます

Starting thread
Thread finished successfully

しかし、どういうわけか、アプリは次のエラーで終了します

03-27 02:48:39.282: E/AndroidRuntime(956): Uncaught handler: thread Thread-9 exiting due to uncaught exception
03-27 02:48:39.293: E/AndroidRuntime(956): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-27 02:48:39.293: E/AndroidRuntime(956):  at android.view.ViewRoot.checkThread(ViewRoot.java:2683)

誰かが私に見せたり、エラーの原因を説明してくれたりすると、とてもありがたいです

4

2 に答える 2

2

問題は、progressBar.dismiss(); 別のスレッドで実行され、UI スレッドで実行するには、次のようにします。

    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            progressBar.dismiss();
        }
    });
于 2012-03-27T04:46:51.947 に答える
1

ProgressDialogはビューであり、UIスレッド(またはメインスレッド)でのみアクセスできます。AsyncTaskスレッドの代わりに使用します。

編集
この公式リンクは、AsyncTaskのコツをつかむのに役立ちます。覚えておくべきことは、doInBackground()メソッドは、データ読み込みメソッド、つまりfetch_data()を配置する必要がある別のスレッドで実行されることです。メソッドの実行が完了すると、onPostExecute()が呼び出され、UIスレッドで実行され、ダイアログを閉じることができます。onPreExecute()メソッドでダイアログを開始できます。
このコンテキストでは、onProgressUpdate()メソッドは必要ありませんが、参考までに、publishProgress()呼び出しを使用してロードがまだ機能している間にUIスレッドのビューを更新するために使用されます(将来AsyncTaskを使用する場合)。

PS: doInBackground()メソッドのみが別のスレッドで実行され、他のすべてのメソッドはUIスレッドで実行されます。UI以外のスレッドでビューにアクセスしないという規則は、ここでも適用されます。

于 2012-03-27T03:15:17.847 に答える