Tôi đã viết một ListActivity có bộ điều hợp danh sách tùy chỉnh. Danh sách đang được cập nhật từ một ContentProvider khi onCreate được chạy. Tôi cũng có một dịch vụ được bắt đầu khi tôi chạy ứng dụng và nó lần đầu tiên cập nhật ContentProvider, sau đó gửi một Broadcast rằng nội dung đã được cập nhật.
Danh sách của tôiKích hoạt nhận được chương trình phát và cố gắng cập nhật ListView của tôi. Vấn đề của tôi là, tôi nhận được lỗi liên tục về dữ liệu adapter ListView thay đổi mà không có ListView được thông báo. Tôi gọi phương thức notifyDataSetChanged()
trên bộ điều hợp danh sách của tôi ngay sau khi tôi cập nhật nó. Những gì nó có vẻ như đang xảy ra là danh sách vẫn đang trong quá trình được cập nhật sau khi lần đầu tiên gọi onCreate khi nó nhận được phát sóng từ dịch vụ để cập nhật, vì vậy nó sẽ cố gắng cập nhật ListView của tôi trước khi nó hoàn thành cập nhật từ lần chạy đầu tiên. Điều này có nghĩa không? Đây là một số mã của tôi.Thay đổi dữ liệu bộ điều hợp ListView mà không ListView được thông báo
LƯU Ý: Dịch vụ hoạt động bình thường, dịch vụ này nhận dữ liệu mới và cập nhật Trình hiển thị nội dung của tôi và tôi sẽ phát sóng trong hoạt động của mình khi cập nhật.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
getPrefs();
setContentView(R.layout.main);
// Setup preference listener
preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(listener);
// Setup report list adapter
ListView nzbLv = (ListView) findViewById(R.id.report_list);
nzbla = new NZBReportListAdaptor(ctx);
getReports();
nzbla.setListItems(report_list);
nzbLv.setAdapter(nzbla);
// Broadcast receiver to get notification from NZBService to update ReportList
registerReceiver(receiver,
new IntentFilter(NZBService.BROADCAST_ACTION));
startService(new Intent(ctx, NZBService.class));
}
@Override
public void onResume() {
super.onResume();
timerHandler.resume();
new updateSabQueue().execute();
//updateList();
}
@Override
public void onPause() {
super.onPause();
timerHandler.pause();
unregisterReceiver(receiver);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Toast.makeText(ctx, "NZBService broadcast recieved", Toast.LENGTH_SHORT).show();
updateReportList();
}
};
private void updateReportList() {
new updateReportList().execute();
}
private class updateReportList extends AsyncTask<Void, Void, Boolean> {
/* (non-Javadoc)
* @see android.os.AsyncTask#onPreExecute()
* Show progress dialog
*/
protected void onPreExecute() {
}
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
* Get new articles from the internet
*/
protected Boolean doInBackground(Void...unused) {
getReports();
return true;
}
/**
* On post execute.
* Close the progress dialog
*/
@Override
protected void onPostExecute(Boolean updated) {
if (updated) {
Log.d(TAG, "NZB report list adapter updated");
synchronized(this) {
nzbla.setListItems(report_list);
}
Log.d(TAG, "NZB report list notified of change");
nzbla.notifyDataSetChanged();
}
}
}
Bây giờ câu hỏi này được trả lời, tôi sẽ đăng mã cập nhật của mình nhằm giúp những người khác có thể gặp phải.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
getPrefs();
setContentView(R.layout.main);
// Setup preference listener
preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(listener);
// Setup report list adapter
ListView nzbLv = (ListView) findViewById(R.id.report_list);
nzbla = new NZBReportListAdaptor(ctx);
report_list.addAll(getReports());
nzbla.setListItems(report_list);
nzbLv.setAdapter(nzbla);
// Broadcast receiver to get notification from NZBService to update ReportList
registerReceiver(receiver,
new IntentFilter(NZBService.BROADCAST_ACTION));
startService(new Intent(ctx, NZBService.class));
}
private class updateReportList extends AsyncTask<Void, Void, ArrayList<Report>> {
/* (non-Javadoc)
* @see android.os.AsyncTask#onPreExecute()
* Show progress dialog
*/
protected void onPreExecute() {
}
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
* Get new articles from the internet
*/
protected ArrayList<Report> doInBackground(Void...unused) {
return getReports();
}
/**
* On post execute.
* Close the progress dialog
*/
@Override
protected void onPostExecute(ArrayList<Report> updated) {
nzbla.setListItems(updated);
nzbla.notifyDataSetChanged();
}
}
private ArrayList<Report> getReports() {
ArrayList<Report> reports = new ArrayList<Report>();
ContentResolver r = getContentResolver();
Cursor c = r.query(NZBReportProvider.CONTENT_URI, null, null, null, NZBReportProvider.ARTICLE_KEY_ROWID + " DESC");
startManagingCursor(c);
Log.d(TAG, "NZBReport cursor.getCount=" + c.getCount());
int title = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_TITLE);
int desc = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_DESCRIPTION);
int cat = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_CAT);
int size = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_SIZE);
int link = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_LINK);
int catid = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_CATID);
int date = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_DATE_ADDED);
int group = c.getColumnIndex(NZBReportProvider.ARTICLE_KEY_GROUP);
if (c.getCount() > 0) {
c.moveToFirst();
do {
URL url = null;
try {
url = new URL(c.getString(link));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
reports.add(new Report(c.getString(title), url, c.getString(desc), c.getString(cat), c.getString(date), c.getString(size), c.getInt(catid), c.getString(group)));
} while (c.moveToNext());
}
return reports;
}
Đây chính xác là vấn đề. Bộ điều hợp danh sách của tôi được hỗ trợ bởi một ArrayList của các đối tượng "report_list" và tôi đang sửa đổi nó trực tiếp trong phương thức getReports của tôi đang thực hiện trên một luồng riêng biệt.Tôi đã sửa đổi phương thức getReports của mình để hoạt động trên một ArrayList cục bộ và trả về nó (và chuyển nó vào phương thức onPostExecute của tôi). Trong khi tôi nhận thức được thực tế rằng tôi không thể hoạt động trên dữ liệu bộ điều hợp danh sách của mình bên ngoài chuỗi giao diện người dùng, tôi đã không nắm bắt nó 100% cho đến khi nó thất bại và buộc tôi tìm ra chính xác (hoặc hỏi chính xác hơn để được giúp đỡ ở đây!) Cảm ơn Qberticus! – brockoli