Информация:
У меня есть RecyclerView
, и я заполняю его списком данных ArrayList внутри класса ListAdapter
. Я получаю данные для dataList из таблицы SQLiteDatabase
: TABLE_USERdETAIL в классе DbHelper
. Я пытаюсь реализовать реорганизацию перетаскивания в RecyclerView
с помощью класса SimpleItemTouchHelperCallback
; однако, хотя теперь я могу перемещать элементы RecyclerView
, список не сортируется и не сортируется; Я могу только временно перетаскивать элементы списка друг на друга, как показано на рисунке ниже, но это означает, что он будет постоянно помещать элементы списка в любое положение, которое он удерживал:
Я ожидаю, что проблема будет в классе ListAdapter
, внутри метода onItemMove, но я не знаю, как решить мою проблему.
Вопрос: Как мне сделать эту функцию перетаскивания фактически реорганизовать список данных RecyclerView
?
Обновление 5: Я обновил текущий код для дальнейшей помощи.
Класс ListAdapter
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListViewHolder> {
Context context;
List<UserData> dataList = new ArrayList<>();
LayoutInflater inflater;
Listener listener;
DbHelper dbHelper;
public interface Listener {
void nameToChnge(String name);
}
public ListAdapter(Context context, List<UserData> dataList1) {
this.context = context;
this.dataList = dataList1;
//this.listener= (Listener) context;
inflater = LayoutInflater.from(context);
}
@Override
public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View convertView = inflater.inflate(R.layout.recylerview_one, parent, false);
ListViewHolder viewHolder = new ListViewHolder(convertView);
return viewHolder;
}
@Override
public void onBindViewHolder(ListViewHolder holder, final int position) {
holder.tv_name.setText(dataList.get(position).name);
holder.tv_quantity.setText(dataList.get(position).quantity);
holder.tv_description.setText(dataList.get(position).description + " ");
if(dataList.get(position).description.isEmpty()) {
holder.tv_description.setVisibility(View.GONE);
}
holder.relLayout.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
String s = dataList.get(position).id;
Integer stringo = Integer.parseInt(s);
Intent intent = new Intent(context, ItemEditActivity.class);
intent.putExtra("ItemNumber", stringo);
context.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return dataList.size();
}
class ListViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
TextView tv_name, tv_quantity, tv_description;
RelativeLayout relLayout;
public ListViewHolder(View itemView) {
super(itemView);
tv_name = (TextView) itemView.findViewById(R.id.nameDisplay);
tv_quantity = (TextView) itemView.findViewById(R.id.quantityDisplay);
tv_description = (TextView) itemView.findViewById(R.id.descriptionDisplay);
relLayout = (RelativeLayout) itemView.findViewById(R.id.relLayout);
}
@Override
public void onItemSelected() {
Log.d("ListViewHolder", "item selected");
}
@Override
public void onItemClear() {
Log.d("ListViewHolder", "item clear");
for (int count = 0; count < dataList.size(); count++) {
UserData u = dataList.get(count);
u.setSort(count);
dbHelper.updateUserData(u);
}
notifyDataSetChanged();
}
}
public void onItemDismiss(int position) {
dataList.remove(position);
//dbHelper = DbHelper.getInstance(context);
//dbHelper.deleteRowItem(position + 1);
notifyItemRemoved(position);
}
//Collections.swap(dataList, fromPosition, toPosition);
//notifyItemMoved(fromPosition, toPosition);
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(dataList, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(dataList, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
}
Класс SimpleItemTouchHelperCallback
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final ListAdapter mAdapter;
public SimpleItemTouchHelperCallback(ListAdapter adapter) {
mAdapter = adapter;
}
@Override
public boolean isLongPressDragEnabled() {return true; }
@Override
public boolean isItemViewSwipeEnabled() { return false; }
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
Log.i("ADAPTER", "----DRAGGING----");
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}
}
Класс DbHelper
Открытый класс DbHelper расширяет SQLiteOpenHelper {
private static final String DATABASE_NAME = "UserDatabase";
private static final int DATABASE_VERSION = 2;
private static DbHelper mDbHelper;
public static String TABLE_USERdETAIL = "userdetail";
private static final String _ID = "_id";
private static final String SORT_ID = "sort_id";
private static final String NAME = "name";
private static final String QUANTITY = "quantity";
private static final String WEIGHT = "weight";
private static final String WEIGHTTOTAL = "weighttotal";
private static final String VALUE = "value";
private static final String VALUETOTAL = "valuetotal";
private static final String DESCRIPTION = "description";
public static synchronized DbHelper getInstance(Context context) {
if (mDbHelper == null) {
mDbHelper = new DbHelper(context.getApplicationContext());
}
return mDbHelper;
}
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_USERDETAIL_TABLE = "CREATE TABLE " + TABLE_USERdETAIL +
"(" +
_ID + " INTEGER PRIMARY KEY , " +
SORT_ID + " INTEGER," +
NAME + " TEXT," +
QUANTITY + " INTEGER," +
WEIGHT + " INTEGER," +
WEIGHTTOTAL + " INTEGER," +
VALUE + " INTEGER," +
VALUETOTAL + " INTEGER," +
DESCRIPTION + " TEXT" +
")";
db.execSQL(CREATE_USERDETAIL_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != newVersion) {
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + WEIGHT + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + WEIGHTTOTAL + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + VALUE + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + VALUETOTAL + " INTEGER DEFAULT 0");
}
}
/**
Insert a user detail into database
*/
public void insertUserDetail(UserData userData) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(SORT_ID, userData.sort_id);
values.put(NAME, userData.name);
values.put(QUANTITY, userData.quantity);
values.put(WEIGHT, userData.weight);
values.put(WEIGHTTOTAL, userData.weighttotal);
values.put(VALUE, userData.value);
values.put(VALUETOTAL, userData.valuetotal);
values.put(DESCRIPTION, userData.description);
db.insertOrThrow(TABLE_USERdETAIL, null, values);
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
public void updateUserDetail(int id, String v1, String v2, String v3, String v4, String v5, String v6, String v7){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(NAME, v1);
values.put(QUANTITY, v2);
values.put(DESCRIPTION, v3);
values.put(WEIGHT, v4);
values.put(WEIGHTTOTAL, v5);
values.put(VALUE, v6);
values.put(VALUETOTAL, v7);
db.update(TABLE_USERdETAIL, values, "_id="+id, null);
}
/**
fetch all data from UserTable
*/
public List<UserData> getAllUser() {
List<UserData> usersdetail = new ArrayList<>();
String USER_DETAIL_SELECT_QUERY = "SELECT * FROM " + TABLE_USERdETAIL + " ORDER BY " + SORT_ID + " COLLATE NOCASE;";
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery(USER_DETAIL_SELECT_QUERY, null);
try {
if (cursor.moveToFirst()) {
do {
UserData userData = new UserData();
userData.id = cursor.getString(cursor.getColumnIndex(_ID));
userData.sort_id = cursor.getInt(cursor.getColumnIndex(SORT_ID));
userData.name = cursor.getString(cursor.getColumnIndex(NAME));
userData.quantity = "Quantity: " + cursor.getString(cursor.getColumnIndex(QUANTITY));
userData.weight = cursor.getString(cursor.getColumnIndex(WEIGHT));
userData.weighttotal = cursor.getString(cursor.getColumnIndex(WEIGHTTOTAL));
userData.value = cursor.getString(cursor.getColumnIndex(VALUE));
userData.valuetotal = cursor.getString(cursor.getColumnIndex(VALUETOTAL));
userData.description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));
usersdetail.add(userData);
} while (cursor.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
return usersdetail;
}
/**
Delete single row from UserTable
*/
void deleteRow(String name) {
SQLiteDatabase db = getWritableDatabase();
try {
db.beginTransaction();
db.execSQL("delete from " + TABLE_USERdETAIL + " where name ='" + name + "'");
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
void deleteRowItem(int id) {
SQLiteDatabase db = getWritableDatabase();
try {
db.beginTransaction();
db.execSQL("delete from " + TABLE_USERdETAIL + " where _id ='" + id + "'");
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
public UserData getSingleUserDetail(String userId) {
SQLiteDatabase db = this.getWritableDatabase();
UserData userData = null;
//Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_USERdETAIL, null);
// this is the code to order the RecyclerView by _ID:
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_USERdETAIL + " WHERE " + _ID + "= ?", new String[]{userId});
try {
while (cursor.moveToNext()) {
userData = new UserData();
userData.name = cursor.getString(cursor.getColumnIndex(NAME));
userData.quantity = cursor.getString(cursor.getColumnIndex(QUANTITY));
userData.weight = cursor.getString(cursor.getColumnIndex(WEIGHT));
userData.weighttotal = cursor.getString(cursor.getColumnIndex(WEIGHTTOTAL));
userData.value = cursor.getString(cursor.getColumnIndex(VALUE));
userData.valuetotal = cursor.getString(cursor.getColumnIndex(VALUETOTAL));
userData.description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));
}
cursor.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
return userData;
}
public int getTotalWeight() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cur = db.rawQuery("SELECT SUM(WEIGHTTOTAL) FROM userdetail", null);
if(cur.moveToFirst())
{
return cur.getInt(0);
}
cur.close();
return getTotalWeight();
}
public int getTotalQuantity() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cur = db.rawQuery("SELECT SUM(QUANTITY) FROM userdetail", null);
if(cur.moveToFirst())
{
return cur.getInt(0);
}
cur.close();
return getTotalQuantity();
}
public int getTotalValue() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cur = db.rawQuery("SELECT SUM(VALUETOTAL) FROM userdetail", null);
if(cur.moveToFirst())
{
return cur.getInt(0);
}
cur.close();
return getTotalValue();
}
public int getMaxColumnData() {
SQLiteDatabase db = this.getWritableDatabase();
final SQLiteStatement stmt = db
.compileStatement("SELECT MAX(SORT_ID) FROM " + TABLE_USERdETAIL);
return (int) stmt.simpleQueryForLong();
}
public void updateUserData(UserData userData) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(NAME, userData.getName());
values.put(QUANTITY, userData.getQuantity());
values.put(DESCRIPTION, userData.getDescription());
values.put(WEIGHT, userData.getWeight());
values.put(WEIGHTTOTAL, userData.getWeighttotal());
values.put(VALUE, userData.getValue());
values.put(VALUETOTAL, userData.getValuetotal());
values.put(SORT_ID, userData.getSort());
Log.i("DBhelper", "USER UPDATED = " + userData.getName());
db.update(TABLE_USERdETAIL, values, _ID + "=?", new String[]{String.valueOf(userData.getId())});
}
}
UserDatah2 >
import java.io.Serializable;
public class UserData implements Serializable {
String id, name, quantity, weight, weighttotal, value, valuetotal, description;
int sort_id;
public UserData() {
super();
}
public void setId(String id){
this.id= id;
}
public String getId(){
return id;
}
public void setSort(int sort){
this.sort_id= sort;
}
public int getSort(){
return sort_id;
}
public void setName(String name){
this.name= name;
}
public String getName(){
return name;
}
public void setDescription(String description){
this.description= description;
}
public String getDescription(){
return description;
}
public void setQuantity(String quantity){
this.quantity= quantity;
}
public String getQuantity(){
return quantity;
}
public void setWeight(String weight){
this.weight= weight;
}
public String getWeight(){
return weight;
}
public void setWeighttotal(String weighttotal){
this.weighttotal= weighttotal;
}
public String getWeighttotal(){
return weighttotal;
}
public void setValue(String value){
this.value= value;
}
public String getValue(){
return value;
}
public void setValuetotal(String valuetotal){
this.quantity= valuetotal;
}
public String getValuetotal(){
return quantity;
}
}
Класс ItemTouchHelperViewHolder
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
MainActivity
public class MainActivity extends AppCompatActivity implements ListAdapter.Listener {
RecyclerView recyclerView;
DbHelper dbHelper;
ListAdapter adapter;
private ItemTouchHelper mItemTouchHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = DbHelper.getInstance(getApplicationContext());
recyclerView = (RecyclerView) findViewById(R.id.rv_contactlist);
adapter = new ListAdapter(this, dbHelper.getAllUser());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ItemTouchHelper.Callback callback =
new SimpleItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.about_task:
Intent intentChangeActivity2 = new Intent(MainActivity.this, AboutActivity.class);
startActivity(intentChangeActivity2);
return true;
case R.id.encumbrance_task:
Intent intentChangeActivity = new Intent(MainActivity.this, EncumbranceActivity.class);
startActivity(intentChangeActivity);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onResume() {
super.onResume();
dbHelper = DbHelper.getInstance(getApplicationContext());
recyclerView = (RecyclerView) findViewById(R.id.rv_contactlist);
adapter = new ListAdapter(this, dbHelper.getAllUser());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
@Override
public void nameToChnge(String name) {
dbHelper.deleteRow(name);
adapter = new ListAdapter(this, dbHelper.getAllUser());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
Журнал ошибок:
8-26 11:20:49.443 23533-23533/name.appE/AndroidRuntime: FATAL EXCEPTION: main
Process: name.app, PID: 23533
java.lang.NullPointerException: Attempt to invoke virtual method 'void name.app.DbHelper.updateUserData(name.app.UserData)' on a null object reference
at name.app.ListAdapter$ListViewHolder.onItemClear(ListAdapter.java:95)
at name.app.SimpleItemTouchHelperCallback.clearView(SimpleItemTouchHelperCallback.java:63)
at android.support.v7.widget.helper.ItemTouchHelper$3.onAnimationEnd(ItemTouchHelper.java:619)
at android.support.v4.animation.HoneycombMr1AnimatorCompatProvider$AnimatorListenerCompatWrapper.onAnimationEnd(HoneycombMr1AnimatorCompatProvider.java:115)
at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1149)
at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1309)
at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
at android.animation.AnimationHandler.-wrap2(AnimationHandler.java)
at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:869)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:616)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)