问题
I know that this question is asked many times but i can't seem to make it work in my app
I create custom adapter that extends BaseAdapter, and inside it I put listener of drag and drop function to rearrange the order of the items on the list.
so I need to call notifydatasetchanged when drop action is performed, and I did, but don't seem to reorder the data even though when I print out the data to LogCat is already sorted the way I want it.
I try recommendation like using asyncTask, Activity.runOnUIThread but no result for me. I also that's not very suitable for me since i calling it inside the adapter itself, though I called it from another class inside the adapter.
The data for my adapter I provide inside the adapter itself, get from local DB.
Please help me and take a look at my code:
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;
}
}
}
}
}
回答1:
You are messing with your getView
's implementation.
if (v == null)
you should only inflate the View
you want to fill up with your dataset. I will try something like:
@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;
}
回答2:
try
CategoryAdapter. notifyDataSetChanged()
When ever you have to refresh an adapter your should enter his name before notifydatasetchanged();
来源:https://stackoverflow.com/questions/15242087/notifydatasetchange-not-working