У меня есть RecyclerView
внутри AppCompatActivity
. Вставки и изменения элементов отображаются и анимируются правильно после поворота устройства.
Проблема возникает, когда вы:
- Нажмите на элемент в
RecyclerView
. - Откроется
DialogFragment
с предложением удалить элемент. - Поверните устройство.
- Подтвердите удаление в диалоговом окне.
- Проверьте список массивов. Товар был удален.
RecyclerView
по-прежнему показывает элемент.
Пробовал использовать notifyDataSetChanged
вместо notifyItemRemoved
, но это тоже не сработало, потому что элемент все еще отображается в RecyclerView
.
Это происходит с любой версией Android.
Упрощенный код обработки процесса:
public class MyAppCompatActivity extends AppCompatActivity {
int positionOfDeletedItem;
MyObjectRecyclerViewAdapter adapter;
ArrayList<MyObject> someTestData;
MyItemDeletionHandler deletionHandlerRemover;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity_layout);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
positionOfDeletedItem = 1;
deletionHandlerRemover = new MyItemDeletionHandler(this);
someTestData = new ArrayList<MyObject>(3);
someTestData.add(new MyObject("A"));
someTestData.add(new MyObject("B"));
someTestData.add(new MyObject("C"));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyObjectRecyclerViewAdapter(new MyAdapterOnClickEvent.OnItemClick() {
@Override
public void onClick(int posicion, int idViaje, View view) {
String tag = "Some tag value";
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag(tag);
if(prev != null)
ft.remove(prev);
ft.addToBackStack(null);
DialogFragment newFragment = MyDeletionConfirmationDialog.newInstance(deletionHandlerRemover);
newFragment.show(ft, tag);
}
}, someTestData);
recyclerView.setAdapter(adapter);
}
private final static class MyItemDeletionHandler extends Handler {
private final WeakReference<MyAppCompatActivity> theActivity;
private MyItemDeletionHandler(MyAppCompatActivity act) {
theActivity = new WeakReference<MyAppCompatActivity>(act);
}
@Override
public void handleMessage(Message msg) {
MyAppCompatActivity activity = theActivity.get();
if(activity != null) {
if(msg.what == 1) {
activity.deleteTheItem();
}
}
}
}
public void deleteTheItem() {
someTestData.remove(positionOfDeletedItem);
adapter.notifyItemRemoved(positionOfDeletedItem);
}
}
public class MyDeletionConfirmationDialog extends DialogFragment {
private Message handlerMessage;
public static MyDeletionConfirmationDialog newInstance(Handler callbackHandler) {
MyDeletionConfirmationDialog myDialog = new MyDeletionConfirmationDialog();
Bundle args = new Bundle();
args.putParcelable("handlerMessage", callbackHandler.obtainMessage(1, true));
myDialog.setArguments(args);
return myDialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handlerMessage = getArguments().getParcelable("handlerMessage");
}
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setMessage("Some message");
alertDialogBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final Message toSend = Message.obtain(handlerMessage);
toSend.sendToTarget();
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
Dialog dialog = alertDialogBuilder.create();
dialog.setCanceledOnTouchOutside(true);
return dialog;
}
}
Как заставить RecyclerView
работать правильно?
Редактировать 1:
У меня есть другие RecyclerView
, в которых это работает правильно. Единственная разница в том, что они находятся внутри Fragment
s вместо AppCompatActivity
. Я подозреваю, что это как-то связано с событиями onDetachedFromWindow
и onAttachedToWindow
из RecyclerView
.
Редактировать 2:
Если диалоговое окно закрыто (шаг 4) и снова открыто, оно работает как положено.
Редактировать 3:
Если RecyclerView
извлекается как Fragment
, проблема исчезает и работает как положено. Невозможно, чтобы описанный выше вариант использования работал правильно в сочетании с AppCompatActivity
вместо Fragment
.
RecyclerView
не обновляется соответствующим образом, он по-прежнему показывает удаленный элемент. - person OneEyeQuestion   schedule 24.04.2016onConfigurationChange
и закрыть диалог, отображаемый на экране. Диалог, отображаемый на экране, не связан с жизненным циклом активности/фрагмента, поэтому он остается на экране. - person Reaz Murshed   schedule 24.04.2016RecyclerViews
, которые следуют тому же варианту использования и работают правильно. Этот просто сбил меня с толку. Я обновлю свой вопрос с некоторым предположением, которое, по моему мнению, может быть причиной проблемы. - person OneEyeQuestion   schedule 24.04.2016MyItemDeletionHandler
не должен компилироваться как написано. Это статический внутренний класс, поэтому он не должен иметь доступа к членам экземпляраMyAppCompatActivity
. - person Karakuri   schedule 07.06.2016MyDeletionConfirmationDialog
? - person Karakuri   schedule 07.06.2016DialogFragment
, который в методеonCreateDialog
используетAlertDialog.Builder
для создания диалога и назначает вsetPositiveButton
прослушиватель, который выполняетfinal Message toSend = Message.obtain(callbackHandler.obtainMessage(1, true)); toSend.sendToTarget();
. Этого достаточно или нужен полный код? В сводке есть простое диалоговое окно подтверждения. - person OneEyeQuestion   schedule 08.06.2016NullPointerException
, когда вы вызываетеsendToTarget()
для этого объекта сообщения. - person Karakuri   schedule 08.06.2016LoaderManager
. Но я перепостил код с упрощенной версией без доступа к базе данных, которая все еще показывает проблему. Я обновлю описание. - person OneEyeQuestion   schedule 09.06.2016