我有一个使用BaseAdapter的ListView,ListView位于ViewGroup中。
当我从另一个线程通过runOnUiThread()调用notifyDataSetChanged()时,ListView本身没有更新。只有当我触摸并拖动,换句话说,尝试滚动时,ListView才会更新。
我发现很多人在从UI线程以外的另一个线程调用notifyDataSetChanged()时遇到了问题,但我没有这样做,而且仍然有问题。
下面的代码似乎是再现问题的最低限度。
public class MyMainActivity extends Activity
{
public MyStringViewGroup StringViewGroup = null;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
StringViewGroup = new MyStringViewGroup(this);
setContentView(StringViewGroup);
new OtherThread(this).start();
}
public void UpdateStringList() {runOnUiThread(new Runnable() {public void run()
{
StringViewGroup.UpdateStringList();
}});}
}
class OtherThread extends Thread
{
MyMainActivity Main = null;
OtherThread(MyMainActivity main)
{
Main = main;
}
@Override public void run()
{
try {sleep(2000);} catch (InterruptedException e) {}
Main.UpdateStringList();
}
}
class MyStringViewGroup extends ViewGroup
{
ListView StreamListView = null;
MyStringListAdapter StringListAdapter = null;
ArrayList<String> StringArray = new ArrayList<String>();
public MyStringViewGroup(MyMainActivity context)
{
super(context);
StreamListView = new ListView(context);
StreamListView.setId(android.R.id.list);
addView(StreamListView);
StringListAdapter = new MyStringListAdapter(StringArray);
StreamListView.setAdapter(StringListAdapter);
}
public void UpdateStringList()
{
StringArray.add("Row 1");
StringArray.add("Row 2");
StringArray.add("Row 3");
StringListAdapter.notifyDataSetChanged();
}
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
StreamListView.layout(left, top, right, bottom);
}
public class MyStringListAdapter extends BaseAdapter
{
ArrayList<String> StringArray = null;
public MyStringListAdapter(ArrayList<String> stringArray) {StringArray = stringArray;}
@Override public int getCount() {return StringArray.size();}
@Override public String getItem(int position) {return StringArray.get(position);}
@Override public long getItemId(int position) {return position;}
@Override public View getView(int position, View convertView, ViewGroup parent)
{
final TextView textView;
if (convertView == null)
{
textView = new TextView(MyStringViewGroup.this.getContext());
textView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
else
textView = (TextView)convertView;
textView.setText(StringArray.get(position));
return textView;
}
}
}
我注意到的是,适配器中的getView()被调用,然后我尝试滚动,而不是在滚动之前,这三行出现,因此适配器显然已更新。
那么,通过runOnUiThread()调用时有什么不同?
如果我更改为:
public void UpdateStringList() {StringViewGroup.post(new Runnable() {public void run()
{
StringViewGroup.UpdateStringList();
}});}
并尝试拨打:
UpdateStringList();
从主线程,我得到了相同的问题。
我甚至尝试在listview上调用invalidate()和requestLayout(),但没有结果(无论如何,您不需要这样做,只是为了确保)
这是我需要在ViewGroup中做的事情吗?