1

アダプタと、そのエントリにアダプタを使用するように設定されたスピナー ビューがあります。/assets/ フォルダー内のすべてのファイルのリストからアイテムをアダプターに追加していますが、このタスクに非常に長い時間がかかることがわかりました (1.5Ghz の電話で 2 つのファイルのリストに約 2 秒かかります!)。次に、ワーカー スレッドを使用してリストを収集し、UI スレッドをブロックしないようにしました。ここに私のコードがあります:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.settings);

    adapter = new ArrayAdapter<String>(SettingsActivity.this, android.R.layout.simple_spinner_item, fontsName);       
    Spinner fontsSpinner = (Spinner) findViewById(R.id.settings_font_spinner);
    fontsSpinner.setAdapter(adapter);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);         

    // The thread to gather font names from /assets/fonts/
    thread =  new Thread(){  
        @Override  
        public void run(){  
            try {
                String[] fileList = getAssets().list("fonts");
                if (fileList != null)
                    for (int i=0; i<fileList.length; i++) {
                        adapter.add(fileList[i]);               
                    }
            } catch (IOException e) {
            }                   
            runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    adapter.notifyDataSetChanged();
                }
            });
        }  
    };        
    thread.start(); 

}

しかし、それはエラーとクラッシュを引き起こします:

08-17 13:54:01.017: E/AndroidRuntime(17929): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

runOnUiThread() を正しく使用していますか?! 興味深いことに、このコードはスレッドを使用していないときは完全に機能しますが、UI がブロックされます (これは面倒です)。

これについて何か助けてください。

4

2 に答える 2

3

zapladapter.add(Object)が述べたように、UI スレッドから呼び出す必要があります。

Thread オブジェクトではなく、Android のAsyncTask クラスを使用する必要があります。たとえば、AsyncTask のdoInBackground(Params...)メソッドでファイルからデータをロードし、メソッドでリスト ビューを更新できますonPostExecute(Result)

notifyDataSetChanged()さらに、明示的に呼び出す必要はありません。への呼び出しはadapter.add(Object)、アダプターが変更されたことを ListView に通知します。

于 2012-08-17T09:49:29.010 に答える
0

それ以外の

                for (int i=0; i<fileList.length; i++) {
                    adapter.add(fileList[i]);               
                }

代わりに次を使用します ( が であると仮定しますfontsName) ArrayList<String>

                for (int i=0; i<fileList.length; i++) {
                    fontsName.add(fileList[i]);               
                }

アイデアは、アダプター内の基になるデータを更新し (別のスレッドで実行しても問題ありません)、UI スレッドからの変更についてアダプターに通知することです (notifyDataSetChanged()行ったように使用します)。

于 2012-08-17T09:59:15.107 に答える