我知道 ListViews 中有很多关于 IllegalStateExceptions 的帖子,但没有任何解决方案适合我。希望有人可以帮助我找出我做错了什么。
这是怎么回事?
当我的 SharedPreferences 中的某个属性更新时,我会更新为 ListView 提供数据的 ArrayList,并通知 ListView。IllegalStateException仅在 Android 4 上引发(从不在 Android 2.3 上),当ListView 中的项目数量发生变化并且用户在更新发生时滚动时。
非法状态异常
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131165193, class android.widget.ListView) with Adapter(class com.example.view.StatusActivity$StatusAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1545)
at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4082)
[...]
编码
这是相关活动的最小版本。ListView 更新是从 onSharedPreferenceChanged 触发的,我还确保在 UI 线程上执行更新(与 IllegalStateException 所建议的相反)。
public class StatusActivity extends Activity implements OnSharedPreferenceChangeListener {
private ArrayList<Status> stati;
private ListView listview;
private SharedPreferences prefs;
private StatusAdapter adapter;
private static final int TYPE_STATUS = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_status);
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefs.registerOnSharedPreferenceChangeListener(this);
listview = (ListView) findViewById(R.id.list);
adapter = new StatusAdapter();
}
public void onResume(){
super.onResume();
updateList();
}
public void updateList(){
StatusDAO.initialize(this);
stati = (ArrayList<Status>) StatusDAO.readAll();
adapter.notifyDataSetChanged();
listview.invalidateViews();
listview.refreshDrawableState();
}
private class StatusAdapter extends BaseAdapter {
private Status current;
public int getCount() {
return stati.size();
}
public Object getItem(int position) {
return stati.get(position);
}
public long getItemId(int position) {
return position;
}
public int getItemViewType(int position) {
return TYPE_STATUS;
}
public int getViewTypeCount() {
return 1;
}
public boolean isEnabled(int position) {
return false;
}
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(StatusActivity.this);
final int layout = R.layout.item_status;
convertView = inflater.inflate(layout, parent, false);
}
// [..]
return convertView;
}
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals(Configuration.PREF_LOADINGSTATUS)){
runOnUiThread(new Runnable() {
public void run() {
updateList();
}
});
}
}
}
我不知道如何解决这个问题,因为我已经尝试了互联网上建议的所有内容(确保数据集的更新发生在 UI 线程上;调用 notifyDataSetChanged(); ...)。
我将非常感谢您的帮助和建议,感谢任何帮助!