我有一个使用BaseAdapter的ListView,ListView位于ViewGroup中。 当我从另一个线程通过runOnUiThread()调用notifyDataSetChanged()时,ListView不会自行更新。只有当我触摸并拖动时,换句话说,尝试滚动,ListView更新。
当他们从另一个线程调用notifyDataSetChanged()而不是UI线程时,我得到了很多人有问题,但我没有这样做但仍然有问题。
以下代码似乎是重现问题的最低要求。
public class MyMainActivity extends Activity
{
public MyStringViewGroup StringViewGroup = null;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
StringViewGroup = new MyStringViewGroup(this);
setContentView(StringViewGroup);
// This is the thread I'll call UpdateStringList() from
new OtherThread(this).start();
//UpdateStringList(); // If I call it from here, everything works
}
// This should post the runnable on the UI-thread so StringViewGroup.UpdateStringList() is called from the right thread
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()
{
// Wait 2 seconds
try {sleep(2000);} catch (InterruptedException e) {}
// Call the funktion that add the three rows
Main.UpdateStringList(); // If i call it from here, It's not working
}
}
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);
}
// An ordinary Adapter, nothing special here (I hope)
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中需要做的是我错过了吗?
答案 0 :(得分:0)
好的,我只是想通了你必须在onLayout调用的ListView上调用measure(),如:
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
StreamListView.measure(...);
StreamListView.layout(left, top, right, bottom);
}
当通过runOnUiThread(new Runnable())从另一个线程调用notifyDataSetChanged()时,只会发生错误,这仍然很奇怪,但我认为measure()是必需的。