#android #android-recyclerview
Вопрос:
Я слышал, что если мы хотим удалить какой-либо элемент из нашего списка вторсырья, мы можем использовать этот метод, например:
private void removeItem(int position){
recordingArrayList.remove(position);
notifyItemRemoved(position);
notifyItemChanged(position, recordingArrayList.size());
notifyDataSetChanged();
}
Но, кажется, я что-то упустил, вот мой RecordingListActivity .java
:
public class RecordingListActivity extends AppCompatActivity {
private RecyclerView recyclerViewRecordings;
private BottomNavigationView bottomNavigationView;
private BottomAppBar bottomAppBar;
private ArrayList<Recording> recordingArrayList;
private FloatingActionButton floatingActionButton;
private RecordingAdapter recordingAdapter;
private TextView textViewNoRecordings;
private TimeAgo timeAgo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recording_list);
timeAgo = new TimeAgo();
initViews();
fetchRecordings();
}
private void initViews() {
recordingArrayList = new ArrayList<Recording>();
floatingActionButton = findViewById(R.id.fab);
recyclerViewRecordings = findViewById(R.id.recyclerViewRecordings);
recyclerViewRecordings.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerViewRecordings.setHasFixedSize(true);
new ItemTouchHelper(simpleCallback).attachToRecyclerView(recyclerViewRecordings);
textViewNoRecordings = findViewById(R.id.textViewNoRecordings);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (v.getId() == R.id.fab){
openHome();
}
}
});
}
private void openHome(){
Intent home = new Intent(RecordingListActivity.this, MainActivity.class);
home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(home);
}
private void fetchRecordings() {
File root = android.os.Environment.getExternalStorageDirectory();
String path = root.getAbsolutePath() "/AbdulhaleemRecorderApp/Audios";
Log.d("Files", "Path: " path);
File directory = new File(path);
File[] files = directory.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i ) {
Log.d("Files", "FileName:" files[i].getName());
String fileName = files[i].getName();
String recordingUri = root.getAbsolutePath() "/AbdulhaleemRecorderApp/Audios/" fileName;
Double size = (double) files[i].length() / 1024;
String time = timeAgo.getTimeAgo(files[i].lastModified());
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
Recording recording = new Recording(recordingUri, fileName, date, size, time,false);
recordingArrayList.add(recording);
}
textViewNoRecordings.setVisibility(View.GONE);
recyclerViewRecordings.setVisibility(View.VISIBLE);
setAdaptertoRecyclerView();
} else {
textViewNoRecordings.setVisibility(View.VISIBLE);
recyclerViewRecordings.setVisibility(View.GONE);
}
}
private void setAdaptertoRecyclerView() {
recordingAdapter = new RecordingAdapter(this, recordingArrayList);
recyclerViewRecordings.setAdapter(recordingAdapter);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getBindingAdapterPosition();
removeItem(position);
}
};
private void removeItem(int position){
recordingArrayList.remove(position);
recordingAdapter.notifyItemRemoved(position);
recordingAdapter.notifyItemChanged(position, recordingArrayList.size());
recordingAdapter.notifyDataSetChanged();
}
вот мой RecordingAdapter.java
public class RecordingAdapter extends RecyclerView.Adapter<RecordingAdapter.ViewHolder> {
private ArrayList<Recording> recordingArrayList;
private Context context;
private MediaPlayer mPlayer;
private boolean isPlaying = false;
private int last_index = -1;
public RecordingAdapter(Context context, ArrayList<Recording> recordingArrayList) {
this.context = context;
this.recordingArrayList = recordingArrayList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recording_item_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
setUpData(holder, position);
}
@Override
public int getItemCount() {
return recordingArrayList.size();
}
private void setUpData(ViewHolder holder, int position) {
Recording recording = recordingArrayList.get(position);
holder.textViewName.setText(recording.getFileName());
holder.textViewDate.setText(recording.getDate());
holder.textViewSize.setText(String.format("%.2f", (double) (recording.getSize())) " KB");
holder.textViewTime.setText(recording.getTime());
if (recording.isPlaying()) {
holder.imageViewPlay.setImageResource(R.drawable.ic_pause);
TransitionManager.beginDelayedTransition((ViewGroup) holder.itemView);
holder.seekBar.setVisibility(View.VISIBLE);
holder.seekUpdation(holder);
} else {
holder.imageViewPlay.setImageResource(R.drawable.ic_play);
TransitionManager.beginDelayedTransition((ViewGroup) holder.itemView);
holder.seekBar.setVisibility(View.GONE);
}
holder.manageSeekBar(holder);
}
public class ViewHolder extends RecyclerView.ViewHolder {
SeekBar seekBar;
ImageView imageViewPlay;
ImageView imageViewShare;
ImageView imageViewEdit;
TextView textViewName;
TextView textViewDate;
TextView textViewSize;
TextView textViewTime;
TextView textViewPhoneNumber;
private String recordingUri;
private int lastProgress = 0;
private Handler mHandler = new Handler();
ViewHolder holder;
public ViewHolder(View itemView) {
super(itemView);
final Context vhContext = itemView.getContext();
seekBar = itemView.findViewById(R.id.seekBar);
imageViewPlay = itemView.findViewById(R.id.imageViewPlay);
imageViewShare = itemView.findViewById(R.id.imageViewShare);
imageViewEdit = itemView.findViewById(R.id.imageViewEdit);
textViewName = itemView.findViewById(R.id.textViewRecordingname);
textViewDate = itemView.findViewById(R.id.textViewDate);
textViewSize = itemView.findViewById(R.id.textViewSize);
textViewTime = itemView.findViewById(R.id.textViewTime);
textViewPhoneNumber = itemView.findViewById(R.id.textViewPhoneNumber);
imageViewShare.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
Recording recording = recordingArrayList.get(position);
recordingUri = recording.getUri();
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/mp3");
share.putExtra(Intent.EXTRA_STREAM, recordingUri);
vhContext.startActivity(Intent.createChooser(share, "Share " recording.getFileName() " using:"));
}
});
imageViewPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = getAdapterPosition();
Recording recording = recordingArrayList.get(position);
recordingUri = recording.getUri();
if (isPlaying) {
stopPlaying();
if (position == last_index) {
recording.setPlaying(false);
stopPlaying();
notifyItemChanged(position);
} else {
markAllPaused();
recording.setPlaying(true);
notifyItemChanged(position);
startPlaying(recording, position);
last_index = position;
}
} else {
startPlaying(recording, position);
recording.setPlaying(true);
seekBar.setMax(mPlayer.getDuration());
Log.d("isPlayin", "False");
notifyItemChanged(position);
last_index = position;
}
}
});
}
public void manageSeekBar(ViewHolder holder) {
holder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mPlayer != null amp;amp; fromUser) {
mPlayer.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private void markAllPaused() {
for (int i = 0; i < recordingArrayList.size(); i ) {
recordingArrayList.get(i).setPlaying(false);
recordingArrayList.set(i, recordingArrayList.get(i));
}
notifyDataSetChanged();
}
Runnable runnable = new Runnable() {
@Override
public void run() {
seekUpdation(holder);
}
};
private void seekUpdation(ViewHolder holder) {
this.holder = holder;
if (mPlayer != null) {
int mCurrentPosition = mPlayer.getCurrentPosition();
holder.seekBar.setMax(mPlayer.getDuration());
holder.seekBar.setProgress(mCurrentPosition);
lastProgress = mCurrentPosition;
}
mHandler.postDelayed(runnable, 100);
}
private void stopPlaying() {
try {
mPlayer.release();
} catch (Exception e) {
e.printStackTrace();
}
mPlayer = null;
isPlaying = false;
}
private void startPlaying(final Recording audio, final int position) {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(recordingUri);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e("LOG_TAG", "prepare() failed");
}
//showing the pause button
seekBar.setMax(mPlayer.getDuration());
isPlaying = true;
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
audio.setPlaying(false);
notifyItemChanged(position);
}
});
}
когда я меняю элемент, кажется, что он удален, но когда я открываю другое действие и возвращаюсь снова, удаленный элемент возвращается снова, как будто он никогда не удалялся, в чем проблема?
Ответ №1:
В соответствии с вашим кодом это ожидаемое поведение. Таким образом, ваш код извлекает данные файлов из файловой системы устройства в onCreate()
способе вашей деятельности и создает список представлений файлов. При recordingArrayList.remove(position);
вызове он удаляет элемент из списка представлений, но не файл из файловой системы. Когда вы вызываете другое действие и возвращаетесь, действие со списком создается снова и onCreate()
вызывается снова, и ваш код снова извлекает все файлы из файловой системы устройства и отображает их в списке. Возможным решением может быть: удалите файл из файловой системы, если у вас есть доступ для чтения и записи в эту папку, или сохраните список в своем приложении. Например, в базе данных помещений и добавьте в поле представления файла isDeleted
и используйте данные из базы данных для отображения в списке.
Надеюсь, это поможет!
Комментарии:
1. спасибо, что нашли время объяснить, я сделал то, что вы сказали, и сработал идеально.
Ответ №2:
Вы не сохраняете изменения в файле, и при повторной загрузке действия массив снова извлекается из файла, который не был обновлен.
Ответ №3:
Ваша функция removeItem должна быть в классе адаптера или после удаления вы должны передать список изменений адаптеру и после этого уведомить об изменениях. В вашем случае вы фактически не удаляете элемент из адаптера (потому что список в действии и список в адаптере разные (разные экземпляры)).
Ответ №4:
Сначала удалите элемент из списка, затем обновите свой адаптер notifyItemRangeChanged
, указав новый размер списка, и, самое главное, вам нужно обновить данные, которые вы ищете recycler-view
.
recordingArrayList.remove(position);
notifyItemRangeChanged(position,recordingArrayList.size());
Ответ №5:
Вам просто нужно удалить имя файла из того места, где вы читаете файл, потому что, когда вы удаляете элемент из списка, он не удаляется из файла. Поэтому при удалении также удалите его элемент из списка.
постарайтесь сохранить логику изменения адаптера только в вашем адаптере.
Я предлагаю вам указать имя метода setData(ArrayList<Recording> recordingsList)
в представлении переработчика.
В адаптере записи
public class RecordingAdapter extends RecyclerView.Adapter<RecordingAdapter.ViewHolder> {
private ArrayList<Recording> recordingArrayList;
private Context context;
public RecordingAdapter(Context context, ArrayList<Recording> recordingArrayList) {
this.context = context;
this.recordingArrayList = recordingArrayList;
}
// added
public setData(ArrayList<Recording> recordingsList) {
this.recordingArrayList = recordingsList;
notifyDataSetChanged();
}
}
И когда вы проводите пальцем, чтобы удалить, вызовите setData(RecordingLists)
метод RecordingAdapter
Активность записи в списке
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getBindingAdapterPosition();
recordingArrayList.remove(position);
recordingAdapter.setData(recordingArrayList); // changed
}
};