我在许多notifyDataSetChanged()问题中搜索过而没有找到我的具体案例,所以这里是:
我有一个根线程(由UI线程启动)侦听某些东西。 每次收到消息时,它都会启动一个新线程(让他们称之为子线程)执行某些操作,并在其生命周期结束时通知UI适配器该对象已被添加。
这个程序99.99%的时间有效(我已经强调了很多程序)但在某些情况下我无法理解这个通知不起作用。
我确定问题是listview,因为上面两个语句(setImageBitmap)正常工作,更改了imageViews图像。
在Activity中初始化处理程序并传递给使用线程的类
//class scope variable
private final Handler mHandler = new Handler(new IncomingHandlerCallback(this));
//At the end of the activity class
/**
* ref. https://groups.google.com/forum/#!msg/android-developers/1aPZXZG6kWk/lIYDavGYn5UJ
*/
class IncomingHandlerCallback implements Handler.Callback {
Activity activity;
public IncomingHandlerCallback(Activity activity) {
this.activity = activity;
}
@SuppressWarnings("unchecked")
@Override
public boolean handleMessage(Message msg) {
DeviceUtils.hideKeyboard(activity);
switch (msg.what) {
case EXECUTE_CODE_UPDATE_TCP_COUNT:
updateDebugCounter(true);
break;
.
.
.
case EXECUTE_CODE_UPDATE_LIST_COUNT:
updateDebugCounter(false);
break;
}
return true;
}
}
就像评论所说,声明是here
自定义阵列适配器
public class PlateInfoListAdapter extends ArrayAdapter<PlateInfo> {
private final Activity context;
CheckBox selectAll;
List<PlateInfo> plateList;
AnprInterface anprInterface;
private MobileANPRDetailPopup readingDetailPopup;
public PlateInfoListAdapter(Activity context, List<PlateInfo> plateList, CheckBox selectAll, AnprInterface anprInterface) {
super(context, R.layout.adapter_plate_list, 0,
plateList);
this.context = context;
this.selectAll = selectAll;
this.plateList = plateList;
this.anprInterface = anprInterface;
final LayoutInflater factory = context.getLayoutInflater();
readingDetailPopup = new MobileANPRDetailPopup(context, factory.inflate(R.layout.popup_mobile_anpr_reading_detail, null));
readingDetailPopup.setBackgroundDrawable(Reso.getDrawable(context, R.drawable.grey_border_white_bck));
readingDetailPopup.setOutsideTouchable(true);
readingDetailPopup.update();
}
static class ViewHolder {
protected LinearLayout layout;
protected CheckBox checkBox;
protected TextView date;
protected TextView plate;
protected TextView plateCountry;
protected ImageView blackList;
protected ImageView whiteList;
protected ImageButton readingDetail;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
PlateInfo plateInfo = plateList.get(position);
boolean hotlistDrawn = false;
if(plateList.size() == 1) {
selectAll.setVisibility(View.VISIBLE);
}
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.adapter_plate_list, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.layout = (LinearLayout) view.findViewById(R.id.ll_plate_layout);
viewHolder.checkBox = (CheckBox) view.findViewById(R.id.cb_plate);
viewHolder.plate = (TextView) view.findViewById(R.id.tv_plate_plate);
viewHolder.plateCountry = (TextView) view.findViewById(R.id.tv_plate_country);
viewHolder.date = (TextView) view.findViewById(R.id.tv_plate_data);
viewHolder.blackList = (ImageView) view.findViewById(R.id.iv_plate_blacklist);
viewHolder.whiteList = (ImageView) view.findViewById(R.id.iv_plate_whitelist);
viewHolder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Here we get the position that we have set for the checkbox using setTag.
int getPosition = (Integer) buttonView.getTag();
// Set the value of checkbox to maintain its state.
plateList.get(getPosition).setRowChecked(buttonView.isChecked());
}
});
viewHolder.readingDetail = (ImageButton) view.findViewById(R.id.ib_plate_detail);
viewHolder.readingDetail.setFocusable(false);
viewHolder.readingDetail.setFocusableInTouchMode(false);
viewHolder.readingDetail.setTag(plateInfo);
viewHolder.readingDetail.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(anprInterface.isReading()) {
return;
}
PlateInfo selectedPlateInfo = (PlateInfo) viewHolder.readingDetail.getTag();
if(selectedPlateInfo != null) {
readingDetailPopup.showCentered(v, selectedPlateInfo);
}
}
});
view.setTag(viewHolder);
} else {
view = convertView;
}
ViewHolder holder = (ViewHolder) view.getTag();
// Restore the checked state properly
holder.checkBox.setTag(position);
holder.checkBox.setChecked(plateInfo.isRowChecked());
holder.plate.setText(plateInfo.getPlate());
holder.plateCountry.setText(plateInfo.getPlateCountry());
holder.date.setText(DateUtils.formatHelianDateToCustomHumanDate("HH:mm:ss dd-MM-yyyy", plateInfo.getDate()));
holder.readingDetail.setTag(plateInfo);
if(plateInfo.getBlackWhiteListNote() != null && !plateInfo.getBlackWhiteListNote().equals("")) {
if(plateInfo.getBlackWhiteListNote().contains("WHITELIST")) {
holder.layout.setBackgroundColor(Reso.getColor(context, R.color.red_light));
holder.whiteList.setVisibility(View.VISIBLE);
hotlistDrawn = true;
}
else {
holder.whiteList.setVisibility(View.INVISIBLE);
}
if(plateInfo.getBlackWhiteListNote().contains("BLACKLIST")) {
holder.layout.setBackgroundColor(Reso.getColor(context, R.color.red_light));
holder.blackList.setVisibility(View.VISIBLE);
hotlistDrawn = true;
}
else {
holder.blackList.setVisibility(View.INVISIBLE);
}
}
else {
holder.layout.setBackgroundColor(Reso.getColor(context, R.color.transparent));
holder.whiteList.setVisibility(View.INVISIBLE);
holder.blackList.setVisibility(View.INVISIBLE);
}
if(plateInfo.isRowSelected()) {
if(hotlistDrawn) {
holder.layout.setBackgroundDrawable(Reso.getDrawable(context, R.drawable.list_selector_red_bck_blue_border_normal));
}
else {
holder.layout.setBackgroundDrawable(Reso.getDrawable(context, R.drawable.list_selector_blue_border_normal));
}
}
else if(hotlistDrawn) {
holder.layout.setBackgroundColor(Reso.getColor(context, R.color.red_light));
}
else {
holder.layout.setBackgroundColor(Reso.getColor(context, R.color.transparent));
}
return view;
}
@Override
public int getCount() {
return plateList.size();
}
@Override
public PlateInfo getItem(int position) {
return plateList.get(position);
}
@Override
public boolean hasStableIds() {
return true;
}
}
以下代码由子线程调用。
此处是产生问题的代码:
mHandler.post(new Runnable() {
@Override
public void run() {
mLastPlateImage.setImageBitmap(plateImage);
mLastContextImage.setImageBitmap(contextImageResized);
mPlateInfoList.add(0, plateInfo);
// That is the problem
mPlateListAdapter.notifyDataSetChanged();
System.gc();
}
});