1

Ich aktualisiere meine SQLite-Datenbank mit Cursorloader innerhalb einer Recyclerview, wo ich es durch Ankreuzen der Checkbox, der Wert aktualisiert, aber irgendwie die Aussicht wurde ein Durcheinander. Einige Zeilen haben auch überprüft, aber der Wert ist immer 0, was nicht überprüft werden sollte. Dies geschieht auch, wenn ich eine neue Zeile einfüge.Warum Position Position in Recyclerview ändern, wenn Update-Datenbank sqlite Content-Provider verwenden?

hier mein MainActivity ist, wo ich die Datenbank aktualisiert

public class MainActivity extends AppCompatActivity implements 
    TaskAdapter.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor>{ 

private TaskAdapter mAdapter; 
private FloatingActionButton floatingActionButton; 

private ArrayList<Task> task = new ArrayList<>(); 

private static final int TASKS_LOADER_ID = 0; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    mAdapter = new TaskAdapter(this); 
    mAdapter.setOnItemClickListener(this); 

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 
    recyclerView.setHasFixedSize(true); 
    recyclerView.setAdapter(mAdapter); 
    recyclerView.setLayoutManager(new LinearLayoutManager(this)); 

    floatingActionButton = (FloatingActionButton) findViewById(R.id.fab); 


    /* Click events in floating action button */ 
    floatingActionButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Intent intent = new Intent(getApplicationContext(), AddTaskActivity.class); 
      startActivity(intent); 
     } 
    }); 

    //initialize the loader 
    getSupportLoaderManager().initLoader(TASKS_LOADER_ID, null, this); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    Log.v("dipanggil", "dipanggil jka"); 
    // re-queries for all tasks 
    getSupportLoaderManager().restartLoader(TASKS_LOADER_ID, null, this); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.menu_main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    int id = item.getItemId(); 
    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     Intent intent = new Intent(this, SettingsActivity.class); 
     startActivity(intent); 
     return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 

/* Click events in RecyclerView items */ 
@Override 
public void onItemClick(View v, int position) { 
    //TODO: Handle list item click event 
    Intent intent = new Intent(this, TaskDetailActivity.class); 
    /*b.putLong("ID", task.get(position).getId()); 
    b.putString("DESCRIPTION", task.get(position).getDescription()); 
    b.putInt("PRIORITY", task.get(position).getPriority()); 
    b.putInt("COMPLETE", task.get(position).getComplete()); 
    b.putLong("DUEDATE", task.get(position).getDueDateMillis());*/ 
    intent.putExtra("ID", String.valueOf(task.get(position).getId())); 

    startActivity(intent); 
    Log.v("testti", ""+v.getTag()+" apakah sama "+task.get(position).getId()); 
} 

/* Click events on RecyclerView item checkboxes */ 
@Override 
public void onItemToggled(boolean active, int position) { 
    //TODO: Handle task item checkbox event 
    ContentValues values = new ContentValues(); 

    String stringId = String.valueOf(task.get(position).getId()); 
    Log.v("test = ", ""+task.get(position).getId()); 

    Uri uri = DatabaseContract.CONTENT_URI; 
    uri = uri.buildUpon().appendPath(stringId).build(); 

    if(active) { 
     Log.v("test","tersentuh"); 
     //values.put(DatabaseContract.TaskColumns.IS_COMPLETE, 1); 
     values.put(DatabaseContract.TaskColumns._ID, task.get(position).getId()); 
     values.put(DatabaseContract.TaskColumns.DESCRIPTION, task.get(position).getDescription()); 
     values.put(DatabaseContract.TaskColumns.IS_PRIORITY, task.get(position).getPriority()); 
     values.put(DatabaseContract.TaskColumns.IS_COMPLETE, 1); 
     values.put(DatabaseContract.TaskColumns.DUE_DATE, task.get(position).getDueDateMillis()); 
     getContentResolver().update(uri, 
       values, 
       null, 
       null); 
    }else{ 
     Log.v("test","tidak tersentuh"); 
     values.put(DatabaseContract.TaskColumns._ID, task.get(position).getId()); 
     values.put(DatabaseContract.TaskColumns.DESCRIPTION, task.get(position).getDescription()); 
     values.put(DatabaseContract.TaskColumns.IS_PRIORITY, task.get(position).getPriority()); 
     values.put(DatabaseContract.TaskColumns.IS_COMPLETE, 0); 
     values.put(DatabaseContract.TaskColumns.DUE_DATE, task.get(position).getDueDateMillis()); 
     getContentResolver().update(uri, 
       values, 
       null, 
       null); 
    } 
    // re-queries for all tasks 
    //mAdapter.notifyDataSetChanged(); 
    getSupportLoaderManager().restartLoader(TASKS_LOADER_ID, null, this); 
} 

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 

    return new AsyncTaskLoader<Cursor>(this) { 

     // Initialize a Cursor, this will hold all the task data 
     Cursor mTaskData = null; 

     // onStartLoading() is called when a loader first starts loading data 
     @Override 
     protected void onStartLoading() { 
      if (mTaskData != null) { 
       // Delivers any previously loaded data immediately 
       deliverResult(mTaskData); 
      } else { 
       // Force a new load 
       forceLoad(); 
      } 
     } 

     @Override 
     public Cursor loadInBackground() { 
      try { 
       return getContentResolver().query(DatabaseContract.CONTENT_URI, 
         null, 
         null, 
         null, 
         DatabaseContract.DEFAULT_SORT); 

      } catch (Exception e) { 
       e.printStackTrace(); 
       return null; 
      } 
     } 

     public void deliverResult(Cursor data) { 
      mTaskData = data; 
      super.deliverResult(data); 
     } 
    }; 

} 

@Override 
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 

    while(data.moveToNext()){ 
     long id = data.getLong(data.getColumnIndex(DatabaseContract.TaskColumns._ID)); 
     String description = data.getString(data.getColumnIndex(DatabaseContract.TaskColumns.DESCRIPTION)); 
     long date = data.getLong(data.getColumnIndex(DatabaseContract.TaskColumns.DUE_DATE)); 
     int priority = data.getInt(data.getColumnIndex(DatabaseContract.TaskColumns.IS_PRIORITY)); 
     int complete = data.getInt(data.getColumnIndex(DatabaseContract.TaskColumns.IS_COMPLETE)); 

     try{ 
      Task tasks = new Task(data); 
      task.add(tasks); 
     }catch (Exception e){ 
      e.printStackTrace(); 
     } 
    } 

    mAdapter.swapCursor(data); 
} 

@Override 
public void onLoaderReset(Loader<Cursor> loader) { 
    mAdapter.swapCursor(null); 
} 

}

dies ist der recyclerview Adapter

public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskHolder> { 

/* Callback for list item click events */ 
public interface OnItemClickListener { 
    void onItemClick(View v, int position); 

    void onItemToggled(boolean active, int position); 
} 

/* ViewHolder for each task item */ 
public class TaskHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
    public TaskTitleView nameView; 
    public TextView dateView; 
    public ImageView priorityView; 
    public CheckBox checkBox; 

    public TaskHolder(View itemView) { 
     super(itemView); 

     nameView = (TaskTitleView) itemView.findViewById(R.id.text_description); 
     dateView = (TextView) itemView.findViewById(R.id.text_date); 
     priorityView = (ImageView) itemView.findViewById(R.id.priority); 
     checkBox = (CheckBox) itemView.findViewById(R.id.checkbox); 

     itemView.setOnClickListener(this); 
     checkBox.setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View v) { 
     if (v == checkBox) { 
      completionToggled(this); 
     } else { 
      postItemClick(this); 
     } 
    } 
} 

private Cursor mCursor; 
private OnItemClickListener mOnItemClickListener; 
private Context mContext; 

public TaskAdapter(Context mContext) { 
    this.mContext = mContext; 
} 

public void setOnItemClickListener(OnItemClickListener listener) { 
    mOnItemClickListener = listener; 
} 

private void completionToggled(TaskHolder holder) { 
    if (mOnItemClickListener != null) { 
     mOnItemClickListener.onItemToggled(holder.checkBox.isChecked(), holder.getAdapterPosition()); 
    } 
} 

private void postItemClick(TaskHolder holder) { 
    if (mOnItemClickListener != null) { 
     mOnItemClickListener.onItemClick(holder.itemView, holder.getAdapterPosition()); 
    } 
} 

@Override 
public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    mContext = parent.getContext(); 
    View itemView = LayoutInflater.from(mContext) 
      .inflate(R.layout.list_item_task, parent, false); 

    return new TaskHolder(itemView); 
} 

@Override 
public void onBindViewHolder(TaskHolder holder, int position) { 

    //TODO: Bind the task data to the views 
    // Indices for the _id, description, and priority columns 
    int idIndex = mCursor.getColumnIndex(DatabaseContract.TaskColumns._ID); 
    int descriptionIndex = mCursor.getColumnIndex(DatabaseContract.TaskColumns.DESCRIPTION); 
    int isCompleteIndex = mCursor.getColumnIndex(DatabaseContract.TaskColumns.IS_COMPLETE); 
    int isPriorityIndex = mCursor.getColumnIndex(DatabaseContract.TaskColumns.IS_PRIORITY); 
    int dueDateIndex = mCursor.getColumnIndex(DatabaseContract.TaskColumns.DUE_DATE); 

    //move cursor to wanted data 
    mCursor.moveToPosition(position); 

    // Determine the values of the wanted data 
    final int id = mCursor.getInt(idIndex); 
    String description = mCursor.getString(descriptionIndex); 
    int isComplete = mCursor.getInt(isCompleteIndex); 
    int isPrior = mCursor.getInt(isPriorityIndex); 
    long dueDate = mCursor.getLong(dueDateIndex); 
    Log.v("adapter", " "+DateUtils.getRelativeTimeSpanString(mContext, dueDate)+" "+dueDate); 
    CharSequence date = DateUtils.getRelativeTimeSpanString(mContext, dueDate); 

    holder.itemView.setTag(id); 

    //determine whether to show date or not 
    if(dueDate != Long.MAX_VALUE){ 
     holder.dateView.setVisibility(View.VISIBLE); 
     holder.dateView.setText(date); 
    }else{ 
     holder.dateView.setVisibility(View.GONE); 
    } 
    //determine the priority icon 
    if(isPrior == 0){ 
     holder.priorityView.setImageResource(R.drawable.ic_not_priority); 
    }else{ 
     holder.priorityView.setImageResource(R.drawable.ic_priority); 
    } 
    //determine the text color and description 
    holder.nameView.setText(description); 
    holder.nameView.setState(isComplete); 

    if(isComplete == 1){ 
     holder.checkBox.setChecked(true); 
     holder.nameView.setState(isComplete); 
    } 

    //to chek if due date has passed or not 
    Calendar now = Calendar.getInstance(); 
    Calendar tasksDate = Calendar.getInstance(); 
    tasksDate.setTimeInMillis(dueDate); 
    int result = now.compareTo(tasksDate); 

    if(result >= 0){ 
     holder.nameView.setState(2); 
    } 
    else if(result < 0){ 
     holder.nameView.setState(0); 
    } 


} 

@Override 
public int getItemCount() { 
    return (mCursor != null) ? mCursor.getCount() : 0; 
} 

/** 
* Retrieve a {@link Task} for the data at the given position. 
* 
* @param position Adapter item position. 
* 
* @return A new {@link Task} filled with the position's attributes. 
*/ 
public Task getItem(int position) { 
    if (!mCursor.moveToPosition(position)) { 
     throw new IllegalStateException("Invalid item position requested"); 
    } 

    return new Task(mCursor); 
} 

@Override 
public long getItemId(int position) { 
    return getItem(position).id; 
} 

public Cursor swapCursor(Cursor cursor) { 
    if (mCursor == cursor) { 
     return null; // bc nothing has changed 
    } 
    Cursor temp = mCursor; 
    this.mCursor = cursor; // new cursor value assigned 

    //check if this is a valid cursor, then update the cursor 
    if (cursor != null) { 
     this.notifyDataSetChanged(); 
    } 
    return temp; 
} 

}

wie diese zu lösen? Vielen Dank!

+0

In 'onLoadFinished', warum löschen Sie keine vorherigen Daten aus der Liste? –

+0

Mögliches Duplikat von [CheckBox in RecyclerView prüft weiterhin verschiedene Elemente] (https://stackoverflow.com/questions/32427889/checkbox-in-recyclerview-keeps-on-checking- different- elements) –

+0

@ cricket_007 okay, werde das versuchen – mangkool

Antwort

0

Im folgenden Teil Ihres Codes haben Sie die else-Bedingung nicht angegeben.

if (isComplete == 1){ 
    holder.checkBox.setChecked(true); 
    holder.nameView.setState(isComplete); 
} 

sollten Sie sonst Bedingung behandeln Sie das Kontrollkästchen zu deaktivieren, weil RecyclerView alten Ansichten verwendet.

holder.checkBox.setChecked(isComplete == 1); 
holder.nameView.setState(isComplete); 

Außerdem sollten Sie alte Elemente löschen, bevor Sie die Liste erneut auffüllen.

+0

danke hinzugefügt habe, funktioniert es jetzt großartig. Nachdem ich die vorherige Liste gelöscht habe und die Bedingung else hinzufügen – mangkool

+0

Wenn es funktioniert, vergessen Sie nicht, die Antwort als akzeptiert zu markieren, indem Sie auf das Häkchen neben der Antwort klicken. –

+0

Brauchen nur zwei Zeilen, wenn Sie 'setChecked (isComplete == 1)' –

Verwandte Themen