为什么我不能使用 runOnUiThread() 来更新适配器? [英] Why I can't use runOnUiThread() to update an adapter?

查看:132
本文介绍了为什么我不能使用 runOnUiThread() 来更新适配器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个适配器和一个微调视图,该视图设置为将适配器用于其条目.我正在从/assets/文件夹中所有文件的列表中向适配器添加项目,我发现这个任务需要很长时间(对于 1.5Ghz 手机上的 2 个文件的列表,甚至大约需要 2 秒!).然后我想出了使用工作线程来收集我的列表而不是阻止 UI 线程.这是我的代码:

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.settings);适配器 = 新 ArrayAdapter<String>(SettingsActivity.this, android.R.layout.simple_spinner_item, fontsName);Spinner fontsSpinner = (Spinner) findViewById(R.id.settings_font_spinner);fontsSpinner.setAdapter(适配器);adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);//从/assets/fonts/收集字体名称的线程线程=新线程(){@覆盖公共无效运行(){尝试 {String[] fileList = getAssets().list("fonts");如果(文件列表!= null)for (int i=0; i

但它会导致错误和崩溃:

08-17 13:54:01.017: E/AndroidRuntime(17929): android.view.ViewRootImpl$CalledFromWrongThreadException: 只有创建视图层次结构的原始线程才能触摸其视图.

我是否正确使用了 runOnUiThread()?!有趣的是,这段代码在不使用任何线程时可以完美运行,但会阻塞 UI(这很痛苦).

有什么帮助吗?

解决方案

正如 zapl 提到的,adapter.add(Object) 必须从 UI 线程调用.

您应该使用 Android 的 AsyncTask 类 而不是 Thread 对象.例如,您可以在 AsyncTask 的 doInBackground(Params...) 方法中从文件加载数据,并在 onPostExecute(Result) 方法中更新列表视图.

此外,您不需要显式调用notifyDataSetChanged();调用 adapter.add(Object) 将通知 ListView 适配器已更改.

I have an adapter and a spinner view which is set to use the adapter for it's entries. I'm adding items to adapter from a list of all files in /assets/ folder, I found that this task takes very long time (even about 2 seconds for a list of 2 files on a 1.5Ghz phone!). Then I came up to use a worker thread to gather my list and not block UI thread. here is my code:

@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(); 

}

but it causes an error and crash:

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.

Am I using runOnUiThread() correctly?! It's interesting that this code works perfectly when not using any thread, but it blocks UI (which is a pain).

any help on this please?

解决方案

As zapl mentioned, adapter.add(Object) has to be called from the UI thread.

You should use Android's AsyncTask class rather than a Thread object. You could, for instance, load the data from file in AsyncTask's doInBackground(Params...) method and update the list view in the onPostExecute(Result) method.

Furthermore, you don't need to call notifyDataSetChanged() explicitly; calls to adapter.add(Object) will notify the ListView that the adapter has changed.

这篇关于为什么我不能使用 runOnUiThread() 来更新适配器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆