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

从Handler.post随机调用的android-ArrayAdapter notifyDataSetChanged()不调用GetView,android,multithreading,android-listview,android-arrayadapter,notifydatasetchanged,Android,Multithreading,Android Listview,Android Arrayadapter,Notifydatasetchanged,我在许多notifyDataSetChanged()问题之间进行了搜索,但没有找到我的具体案例,因此如下所示: 问题 我有一个根线程(由UI线程启动),用于侦听某些内容。 每次收到消息时,它都会启动一个新线程(我们称之为子线程),该线程执行一些操作,并且在其生命周期结束时,会通知UI适配器添加了一个对象 这个程序在99.99%的时间内有效(我在程序中强调了很多),但在某些情况下,我无法理解此通知不起作用 我确信问题出在listview上,因为上面两条语句(setImageBitmap)工作正常,

我在许多notifyDataSetChanged()问题之间进行了搜索,但没有找到我的具体案例,因此如下所示:

问题 我有一个根线程(由UI线程启动),用于侦听某些内容。 每次收到消息时,它都会启动一个新线程(我们称之为子线程),该线程执行一些操作,并且在其生命周期结束时,会通知UI适配器添加了一个对象

这个程序在99.99%的时间内有效(我在程序中强调了很多),但在某些情况下,我无法理解此通知不起作用

我确信问题出在listview上,因为上面两条语句(setImageBitmap)工作正常,更改了ImageView图像

代码 在活动中初始化处理程序,并将其传递给使用线程的类

//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;
    }
}
就像评论中说的那样,声明被采纳了

自定义阵列适配器

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
是使用
新处理程序(Looper.getMainLooper())
初始化的?不,我正在用初始化来编辑问题,请给我第二条消息,在主线程上创建活动,以便处理程序最终使用正确的Looper。尽管如此,我还是喜欢直截了当地说出来,以防出人意料。你在哪里向你的处理者发送消息?必须有类似handler.sendMessage(执行\u代码\u更新\u TCP\u计数)的内容;您实际在哪里修改适配器?我看到notifyDataSetChanged,但是您实际上在哪里更新它的内容?
            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();
                }
            });