notifydatasetchange无法正常工作

时间:2013-03-06 08:11:23

标签: android drag-and-drop custom-adapter notifydatasetchanged

我知道这个问题被多次询问,但我似乎无法在我的应用程序中使用它

我创建了扩展BaseAdapter的自定义适配器,在其中我放置了拖放功能的监听器来重新排列列表中项目的顺序。

所以我需要在执行drop动作时调用notifydatasetchanged,我这样做了,但是,即使我将数据打印到LogCat时已经按照我想要的方式排序,但似乎没有对数据重新排序。

我尝试推荐使用asyncTask,Activity.runOnUIThread,但对我没有结果。我也不太适合我,因为我在适配器本身内调用它,虽然我从适配器内的另一个类调用它。

我在适配器内部提供的适配器数据,来自本地数据库。

请帮帮我,看看我的代码:

CategoryAdapter - > customAdapter

public class CategoryAdapter extends BaseAdapter {
private static final String TAG = CategoryAdapter.class.getSimpleName();

private List<CategoryUIO> categoryUIOs;
private Context context;
private LayoutInflater inflater;
private CategorySequenceComparator comparator = new CategorySequenceComparator();

public CategoryAdapter(Activity activity) {
    this.context = activity;
    inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    getData();
}

private void getData() {
    Cursor cursor = MoneyTracker.getCategoryDB().queryAll();
    categoryUIOs = new ArrayList<CategoryUIO>();
    if (cursor != null && cursor.moveToFirst()) {
        do {
            CategoryUIO bo = new CategoryUIO(cursor);
            categoryUIOs.add(bo);
        } while (cursor.moveToNext());
        cursor.close();
    }
    notifyDataSetChanged();
}

private void sortData() {
    if (categoryUIOs != null) {
        Collections.sort(categoryUIOs, comparator);
        notifyDataSetChanged();

        Log.w(TAG, "\n\n");
        for (CategoryUIO uio : categoryUIOs) {
            Log.w(TAG, Utilities.formatString("Name = %s", uio.getName()));
        }
    }
}

@Override
public int getCount() {
    if (categoryUIOs != null) {
        return categoryUIOs.size();
    } else {
        return 0;
    }
}

@Override
public Object getItem(int position) {
    if (categoryUIOs != null) {
        return categoryUIOs.get(position);
    } else {
        return null;
    }
}

@Override
public long getItemId(int position) {
    if (categoryUIOs != null) {
        return ((CategoryUIO) getItem(position)).getId();
    } else {
        return -1;
    }
}

public void refresh() {
    getData();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        v = inflater.inflate(R.layout.row_list, parent, false);
        CategoryUIO uio = ((CategoryUIO) getItem(position));
        v.setTag(uio);
        if (uio != null) {
            final TextView tvItem = (TextView) v.findViewById(R.id.tvItem);
            final ImageView ivMove = (ImageView) v.findViewById(R.id.ivMove);
            final ImageView ivSecured = (ImageView) v.findViewById(R.id.ivSecured);
            tvItem.setText(uio.getDisplayName());
            v.setOnDragListener(new MyDragListener());
            ivMove.setOnTouchListener(new MyTouchListener());

            if (uio.isSecured()) {
                ivSecured.setVisibility(ImageView.VISIBLE);
            } else {
                ivSecured.setVisibility(ImageView.INVISIBLE);
            }
        }
    } else {

    }
    return v;
}

private final class MyTouchListener implements OnTouchListener {
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            View parent = (View) view.getParent();
            CategoryUIO uio = (CategoryUIO) parent.getTag();
            ClipData data = ClipData.newPlainText("label", uio.getDisplayName());
            DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(parent);
            //              shadowBuilder.onProvideShadowMetrics(new Point(parent.getWidth() / 2, parent.getHeight() / 2), new Point(0, 0));
            view.startDrag(data, shadowBuilder, parent, 0);
            //              view.setVisibility(View.INVISIBLE);
            return true;
        } else {
            return false;
        }
    }
}

private final class MyDragListener implements OnDragListener {

    @Override
    public boolean onDrag(View droppedView, DragEvent event) {
        int action = event.getAction();
        switch (action) {
        case DragEvent.ACTION_DRAG_STARTED: {
            return true;
        }
        case DragEvent.ACTION_DRAG_ENTERED: {
            return true;
        }
        case DragEvent.ACTION_DRAG_EXITED: {
            return true;
        }
        case DragEvent.ACTION_DROP: {
            View draggedView = (View) event.getLocalState();
            CategoryBO draggedBO = ((CategoryBO) draggedView.getTag());
            CategoryBO dropedBO = ((CategoryBO) droppedView.getTag());

            // persist the sequence to db
            SQLiteDatabase db = MoneyTracker.getDB();
            db.beginTransaction();
            try {
                // swap the sequence
                int temp = draggedBO.getSequence();
                draggedBO.setSequence(dropedBO.getSequence());
                dropedBO.setSequence(temp);

                ContentValues cv = new ContentValues();
                cv.put(CategoryDB.C_ID, draggedBO.getId());
                cv.put(CategoryDB.C_SEQUENCE, draggedBO.getSequence());
                Response response1 = CategoryBLService.getInstance().update(cv);
                cv = new ContentValues();
                cv.put(CategoryDB.C_ID, dropedBO.getId());
                cv.put(CategoryDB.C_SEQUENCE, dropedBO.getSequence());
                Response response2 = CategoryBLService.getInstance().update(cv);

                // TODO: THIS PART IS NOT NECESSARY IF CALL TO NOTIFYDATASETCHANGED WORKS {
                // the data is updated but seems like notifydatasetchanged in sortData()
                // don't have any effect

                // swap the BOs
                //                  CategoryBO tempBO = draggedBO;
                //                  draggedBO = dropedBO;
                //                  dropedBO = tempBO;
                //
                //                  droppedView.setTag(dropedBO);
                //                  draggedView.setTag(draggedBO);
                //
                //                  // refresh the views
                //                  TextView droppedTvItem = (TextView) droppedView.findViewById(R.id.tvItem);
                //                  droppedTvItem.setText(dropedBO.getDisplayName());
                //                  TextView draggedTvItem = (TextView) draggedView.findViewById(R.id.tvItem);
                //                  draggedTvItem.setText(draggedBO.getDisplayName());
                // TODO: } THIS IS THE END OF UNNECESSARY BLOCK

                if (response1.isSuccess() && response2.isSuccess()) {
                    db.setTransactionSuccessful();
                    sortData();
                    return true;
                } else {
                    return false;
                }
            } finally {
                db.endTransaction();
            }
        }
        case DragEvent.ACTION_DRAG_ENDED: {
            return true;
        }
        default: {
            return true;
        }
        }
    }
}
}

2 个答案:

答案 0 :(得分:1)

CategoryAdapter. notifyDataSetChanged()

当你必须刷新适配器时,你应该在notifydatasetchanged()之前输入他的名字;

答案 1 :(得分:1)

您正在搞乱getView的实施。

if (v == null)

您应该只对要填充数据集的View进行充气。我会尝试类似的事情:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        v = inflater.inflate(R.layout.row_list, parent, false);
        final TextView tvItem = (TextView) v.findViewById(R.id.tvItem);
        final ImageView ivMove = (ImageView) v.findViewById(R.id.ivMove);
        final ImageView ivSecured = (ImageView) v.findViewById(R.id.ivSecured);
     }
        CategoryUIO uio = ((CategoryUIO) getItem(position));
        v.setTag(uio);

        if (uio != null) {

            tvItem.setText(uio.getDisplayName());
            v.setOnDragListener(new MyDragListener());
            ivMove.setOnTouchListener(new MyTouchListener());

            if (uio.isSecured()) {
                ivSecured.setVisibility(ImageView.VISIBLE);
            } else {
                ivSecured.setVisibility(ImageView.INVISIBLE);
            }
        }

    return v;
}