5

У меня есть RecyclerView внутри AppCompatActivity. После поворота устройства отображаются и анимируются вставки и изменения элементов.RecyclerView не обновляется после поворота устройства с открытым диалоговым окном DialogFragment

Проблема происходит, когда вы:

  1. Нажмите на элемент в RecyclerView.
  2. A DialogFragment открывает запрос, если вы хотите удалить элемент.
  3. Поверните устройство.
  4. Подтвердите удаление в диалоговом окне.
  5. Проверьте список массивов. Элемент удален.
  6. 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 правильно работать?


Edit 1:

У меня есть другие RecyclerView сек, в котором это работает правильно. Единственное различие заключается в том, что они находятся внутри Fragment с вместо AppCompatActivity. Я подозреваю, что это как-то связано с событиями onDetachedFromWindow и onAttachedToWindowRecyclerView.


Edit 2:

Если диалоговое окно закрывается (этап 4) и снова открыть это работает, как ожидалось.


Edit 3:

Если RecyclerView извлекается как Fragment проблема исчезает и работает как задумано. Нельзя использовать описанный выше вариант использования в соответствии с AppCompatActivity вместо Fragment.

+0

Когда вы нажимаете на диалог, он должен исчезнуть и удалить элемент в списке. Итак, как же диалог остается, когда вы меняете ориентацию и удаляет данные? –

+0

@ReazMurshed Вариант использования следующий: вы щелкните элемент, чтобы удалить его. Он показывает диалог подтверждения с параметрами («Отмена» и «Удалить»). Вы не нажимаете ни один из параметров. Вы поворачиваете устройство. Диалог по-прежнему открыт. Затем вы выбираете опцию «Удалить», чтобы удалить элемент. Диалоговое окно закрывается. Элемент удален из базы данных. «RecyclerView» не обновляется соответствующим образом, он по-прежнему показывает удаленный элемент. – OneEyeQuestion

+0

Это не правильное решение, но в любом случае этот хак может сделать трюк, который вы хотите. Вы легко можете определить изменение ориентации в 'onConfigurationChange' и можете отклонить диалог, который отображается на экране. Диалог, отображаемый на экране, не связан с жизненным циклом активности/фрагмента, и поэтому он остается на экране. –

ответ

0

У меня возникла аналогичная проблема с RecyclerView. Когда я вытащил левую кнопку, чтобы удалить элемент, а затем повернуть экран, элемент был удален из моего набора данных, но экран не был освежающим, как это обычно делает, когда мы делаем то же действие без вращения. Кажется, что adaptar.notifyItemRemoved() не обновлял экран вообще.

Я использую исходный код Nemanja Kovacevic в качестве отправной точки, но я сделал некоторые изменения на нем (например, добавление элемента, редактирование с помощью диалога, поддержка базы данных и т. Д.).

Итак, я прочитал это post, который дал мне подсказку о том, что может произойти неправильно. Кажется, что adapter.notify все еще указывал на предыдущее предложение адаптера перед вращением. Каждый раз, когда мы вращаем новый адаптер создан на активности: OnCreate

public class MainActivity extends AppCompatActivity 
    implements NavigationView.OnNavigationItemSelectedListener, 
    AddAlertDialog.OnAlertSavedListener, 
    AlertListAdapter.OnItemDeletedListener { 

    static ListAdapter mListAdapter; 
    RecyclerView mRecyclerView; 
    ... 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 
    mRecyclerView = (RecyclerView) findViewById(R.id.mainListView); 
    mDB = new DatabaseTable(this); 

    // Reading all alerts 
    ArrayList<Alert> alerts = mDB.getAllAlerts(); 

    if (mListAdapter == null) 
     mListAdapter = new ListAdapter(this, alerts); 
    } 
} 

Может быть, это не идеальным (создание статических объектов не очень хорошая идея), но решить эту проблему.

Надеюсь, это тоже поможет.

 Смежные вопросы

  • Нет связанных вопросов^_^