5

我在AppCompatActivity內有RecyclerView。在旋轉設備後,會顯示項目插入和更改並正確動畫。使用打開的DialogFragment旋轉設備後,RecyclerView不刷新

問題發生在你:對在RecyclerView項目

  1. 點擊。
  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正常工作?


編輯1:

我有其他RecyclerView S IN此工作正常。唯一的區別是在Fragment s之內,而不是AppCompatActivity。我懷疑這與RecyclerView的事件onDetachedFromWindowonAttachedToWindow有關。


編輯2:

如果對話框被關閉(步驟4),並再次打開它按預期工作。


編輯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); 
    } 
} 

也許這是不理想(創建靜態對象是不是一個好主意),但它解決了這個問題。

我希望它也可以幫助你。