是ArrayAdapter线程安全的机器人?如果没有,我能做些什么来使线程安全的? [英] Is ArrayAdapter thread safe in android? If not, what can I do to make it thread safe?

查看:128
本文介绍了是ArrayAdapter线程安全的机器人?如果没有,我能做些什么来使线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以说,我对<一href="http://developer.android.com/reference/android/widget/ArrayAdapter.html"><$c$c>ArrayAdapter而在code其中我重写<一href="http://developer.android.com/reference/android/widget/ArrayAdapter.html#getView%28int,%20android.view.View,%20android.view.ViewGroup%29"><$c$c>getView(int我,视图V,ViewGroup中G) ,我检索使用当前项<一href="http://developer.android.com/reference/android/widget/ArrayAdapter.html#getItem%28int%29"><$c$c>getItem(i).我可以肯定的说<一href="http://developer.android.com/reference/android/widget/ArrayAdapter.html#getItem%28int%29"><$c$c>getItem(i)将返回即使其他线程操作相同的<一个项目一个href="http://developer.android.com/reference/android/widget/ArrayAdapter.html"><$c$c>ArrayAdapter?

Lets say I extend ArrayAdapter and in the code where I am overriding getView(int i, View v, ViewGroup g), I retrieve the current item using getItem(i). Can I be sure that getItem(i) will return an item even if other threads manipulate the same ArrayAdapter?

我不知道,但我认为答案是否定的。如果是,你有什么建议我做,使之线程安全的?

I am not sure, but I think the answer is no. If it is, what do you suggest I do to make it thread-safe?

推荐答案

这不是ArrayAdapter的问题是线程安全的。 ListView和其他类似的UI部件,与一个适配器工作不允许适配器的内容,他们意外更改。而这不仅仅是由于其他线程 - 你需要告诉有关更改您做出的ListView之前,接下来将尝试与您的适配器进行交互

It's not a matter of ArrayAdapter being thread safe. ListView and other such UI widgets that work with an Adapter do not allow the contents of the adapter to change unexpectedly on them. And this is more than just due to other threads -- you need to tell the ListView about the change you make before it next tries to interact with your adapter.

如果您允许另一个线程来修改适配器,或修改在主线程,但允许其他任何事情发生之前不要告诉ListView控件有关的变化,你会随机(由于比赛)获得异常抛出的ListView约该适配器意外变化。

If you allow another thread to modify the adapter, or modify it on the main thread but don't tell ListView about the change before allowing anything else to happen, you will randomly (due to races) get exceptions thrown by ListView about the adapter changing unexpectedly.

在ArrayAdapter的特殊情况下,如果你使用的API来修改其内容将需要讲述的改变列表视图的照顾。然而,你的必须的主线程上做出这样的改变,以确保该列表视图不尝试访问,你的变化是由点和列表视图之间的适配器讲述了变化

In the specific case of ArrayAdapter if you use the API to modify its contents it will take care of telling the list view about the change. However you must make such changes on the main thread, to make sure that the list view doesn't try to access the adapter between the point where your change is made and the list view is told about that change.

如果你只是做简单的修改ArrayAdapter(添加和删除几个项目),那么你将被罚款,但你必须在主线程上做这些。

If you are only making simple changes to ArrayAdapter (adding and removing a few items), then you will be fine but you must do these on the main thread.

有关更多显著的变化(如说,新数据从服务器适配器获得了新的数据,由于设置为获取),考虑不使用ArrayAdapter,而是实现自己的BaseAdapter的子类。 ArrayAdapter适用于,你有一个简单的小相当静态组数据来显示的情况 - 简单的情况。对于更复杂的东西,你可能会更快乐只是实施BaseAdapter和做数据管理自己。

For more significant changes (such as say the adapter getting a new data set due to a fetch of new data from a server), Consider not using ArrayAdapter and instead implementing your own subclass of BaseAdapter. ArrayAdapter is intended for situations where you have a small simple fairly static set of data to show -- simple situations. For more complicated things, you'll probably be happier just implementing BaseAdapter and doing the data management yourself.

的典型方法在这些复杂的情况下,一个适配器的更新是一个后台线程生成新的数据集,并且一旦可用然后主线程被换入到适配器原子通过调用notifyDataSetChanged(上),以让ListView控件知道数据发生了变化。

The typical way an adapter updates in these complicated situations is that a background thread generates the new data set, and once that is available then on the main thread it is swapped in to the adapter atomically with a call to notifyDataSetChanged() to let the ListView know that the data has changed.

所以我们可以说你是显示一些数据是MyItem对象的数组。保持你的数据在一出戏数组:

So let's say you are showing some data that is an array of MyItem objects. Keep your data in a play array:

ArrayList<MyItem>

实施BaseAdapter的一个子类,显示该列表:

Implement a subclass of BaseAdapter that shows this list:

class MyAdapter extends BaseAdapter<MyItem> {
    ArrayList<MyItem> mItems;

    public int getCount() {
        return mItems != null ? mItems.size() : 0;
    }

    public MyItem getItem(int position) {
        return mItems.get(i);
    }

    ...
}

和现在这里是你可以实现,可以从另一个线程被调用,以提供一个新的数据集被示出的适配器上的功能:

And now here is a function you could implement on the adapter that can be called from another thread to provide a new data set to be shown:

    final Handler mHandler = new Handler();

    void setDataFromAnyThread(final ArrayList<MyItem> newData) {
        // Enqueue work on mHandler to change the data on
        // the main thread.
        mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mItems = newData;
                    notifyDataSetChanged();
                }
            });
    }

当然,如果你使用的AsyncTask做你的数据生成这个已经有一个方便的功能,用于执行下班回来在主线程。同样,你可以使用新的Loader工具来照顾的产生背景。

Of course if you are using AsyncTask to do your data generation this already has a convenient facility for performing that work back on the main thread. Likewise you could use the new Loader facility to take care of the generation in the background.

如果你仍然想使用ArrayAdapter,在功能上面,你可以通过清除当前的数据和添加新的数据到现在空适配器做到这一点。这仅仅是更多的开销并没有真正得到你什么。

And if you still want to use ArrayAdapter, in your function above you could do this by clearing the current data and adding the new data to the now empty adapter. This is just more overhead that doesn't really gain you anything.

这篇关于是ArrayAdapter线程安全的机器人?如果没有,我能做些什么来使线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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