android - 从Handler.post调用的ArrayAdapter notifyDataSetChanged()随机调用GetView

时间:2014-09-26 10:47:28

标签: android multithreading android-listview android-arrayadapter notifydatasetchanged

我在许多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();
                }
            });

0 个答案:

没有答案