IT박스

RecyclerView 저장 / 활동 간 상태 복원

itboxs 2020. 11. 24. 07:48
반응형

RecyclerView 저장 / 활동 간 상태 복원


내 ListView를 RecyclerView로 마이그레이션하고 있습니다. 목록보기를 사용하여 여기설명 된 일반적인 기술을 사용하여 활동 간의 스크롤 위치를 저장하고 복원했습니다.

RecyclerViews로 동일한 작업을 수행하는 방법은 무엇입니까? 액세스 권한 RecyclerView.onSaveInstanceState()있는 protected같으므로 직접 사용할 수 없습니다.


좋아, 내 질문에 답해 보자. 내가 알기로는 레이아웃 코드와 뷰 재활용 코드 (이름)를 분리했기 때문에 레이아웃 상태를 유지하고 복원하는 역할을 담당하는 구성 요소가 이제 LayoutManagerrecyclerview 에서 사용됩니다.

따라서 상태를 저장하려면 동일한 패턴을 사용하지만 recyclerview가 아닌 레이아웃 관리자 에서 사용합니다 .

protected void onSaveInstanceState(Bundle state) {
     super.onSaveInstanceState(state);

     // Save list state
     mListState = mLayoutManager.onSaveInstanceState();
     state.putParcelable(LIST_STATE_KEY, mListState);
}

에서 상태 복원 onRestoreInstanceState():

protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);

    // Retrieve list state and list/item positions
    if(state != null)
        mListState = state.getParcelable(LIST_STATE_KEY);
}

그런 다음 LayoutManager를 업데이트합니다 (에서 수행합니다 onResume()).

@Override
protected void onResume() {
    super.onResume();

    if (mListState != null) {
        mLayoutManager.onRestoreInstanceState(mListState);
    }
}

더 나은 솔루션을 찾았습니다. 이 솔루션에는 다음과 같은 이점이 있습니다.

  1. RecyclerView 상태는 휴대 전화 회전시 저장 및 복원됩니다.
  2. RecyclerView 상태는 RecyclerView를 사용 하여 활동 으로 돌아갈 때 저장되고 복원됩니다 (다른 활동이 표시되는 동안 파괴되지 않았습니다. 즉, onRestoreInstanceState()호출되지 않음 을 의미합니다 !!).

암호

public class ActivityItemList extends AppCompatActivity
{
    private final String KEY_RECYCLER_STATE = "recycler_state";
    private RecyclerView mRecyclerView;
    private static Bundle mBundleRecyclerViewState;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);//set to whatever layout name you have

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);//set to whatever view id you use
        // don't forget to set your adapter
    }

    @Override
    protected void onPause()
    {
        super.onPause();

        // save RecyclerView state
        mBundleRecyclerViewState = new Bundle();
        Parcelable listState = mRecyclerView.getLayoutManager().onSaveInstanceState();
        mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, listState);
    }

    @Override
    protected void onResume()
    {
        super.onResume();

        // restore RecyclerView state
        if (mBundleRecyclerViewState != null) {
            Parcelable listState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
            mRecyclerView.getLayoutManager().onRestoreInstanceState(listState);
        }
    }
}

이 코드를 사용 onPause()하고 onResume()스크롤 위치 - 저장 및 복원

private Parcelable recyclerViewState;
recyclerViewState = mrecyclerView.getLayoutManager().onSaveInstanceState();//save
mrecyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);//restore

이것이 내 솔루션입니다. 항목과 RecyclerView 위치를 모두 복원합니다.

1) onSaveInstanceState 메서드에 리사이클 러 뷰 상태 저장

@Override
protected void onSaveInstanceState(Bundle outState) {
    Parcelable listState = myRecyclerView.getLayoutManager().onSaveInstanceState();
    // putting recyclerview position
    outState.putParcelable(SAVED_RECYCLER_VIEW_STATUS_ID, listState);
    // putting recyclerview items
    outState.putParcelableArrayList(SAVED_RECYCLER_VIEW_DATASET_ID,mDataset);
    super.onSaveInstanceState(outState);
}

2) onCreate 메소드에서 savedInstanceState Bundle 확인

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState==null){
            getRemoteData(); // No saved data, get data from remote
        }else{
            restorePreviousState(); // Restore data found in the Bundle
        }
    }

3) 화면이 회전 된 경우 리사이클 러 뷰 데이터 복원

public void restorePreviousState(){
    // getting recyclerview position
    mListState = mSavedInstanceState.getParcelable(SAVED_RECYCLER_VIEW_STATUS_ID);
    // getting recyclerview items
    mDataset = mSavedInstanceState.getParcelableArrayList(SAVED_RECYCLER_VIEW_DATASET_ID);
    // Restoring adapter items
    mAdapter.setItems(mDataset);
    // Restoring recycler view position
    mRvMedia.getLayoutManager().onRestoreInstanceState(mListState);
}

public class MainActivity extends AppCompatActivity {
Parcelable recyclerViewState;
.......
@Override
    protected void onPause() {
        super.onPause();
        recyclerViewState = MainAnecdotesView.getLayoutManager().onSaveInstanceState();//save
    }
    @Override
    protected void onResume()
    {
        super.onResume();
        if(recyclerViewState!=null)
            MainAnecdotesView.getLayoutManager().onRestoreInstanceState(recyclerViewState);//restore
    }
}

When you use recyclerView.getLayoutManager().onSaveInstanceState() don't forget to check for null:

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);

    if (recyclerView != null) {
        outState.putParcelable(SCROLL_POSITION, recyclerView.getLayoutManager().onSaveInstanceState());
    }
}

Considering that you defined a RecyclerView (mRecyclerView) and a LayoutManager (mLayoutManager) in your code and all is working fine so far, the solution on saving the position (mPosition) of your RecyclerView looks like this:

  1. Variables and constants used:

    private final String RECYCLER_POSITION_KEY = "recycler_position";
    private int mPosition = RecyclerView.NO_POSITION;
    private RecyclerView mRecyclerView;
    private LinearLayoutManager mLayoutManager;
    private static Bundle mBundleState;
    
  2. In onPause method:

    @Override
    protected void onPause()
    {
        super.onPause();
    
        // Save RecyclerView state
        mBundleState = new Bundle();
        mPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();
        mBundleState.putInt(RECYCLER_POSITION_KEY, mPosition);
    }
    
  3. In onResume method:

    @Override
    protected void onResume()
    {
        super.onResume();
    
        // Restore RecyclerView state
        if (mBundleState != null) {
            mPosition = mBundleState.getInt(RECYCLER_POSITION_KEY);
            if (mPosition == RecyclerView.NO_POSITION) mPosition = 0;
            // Scroll the RecyclerView to mPosition
            mRecyclerView.smoothScrollToPosition(mPosition);
        }
    }
    
  4. In onSaveInstanceState method:

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Save RecyclerView state
        outState.putInt(RECYCLER_POSITION_KEY,  mLayoutManager.findFirstCompletelyVisibleItemPosition());
    
        super.onSaveInstanceState(outState);
    }
    
  5. In onRestoreInstanceState method:

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        // Restore RecyclerView state
        if (savedInstanceState.containsKey(RECYCLER_POSITION_KEY)) {
            mPosition = savedInstanceState.getInt(RECYCLER_POSITION_KEY);
            if (mPosition == RecyclerView.NO_POSITION) mPosition = 0;
            // Scroll the RecyclerView to mPosition
            mRecyclerView.smoothScrollToPosition(mPosition);
        }
    
        super.onRestoreInstanceState(savedInstanceState);
    }
    

참고URL : https://stackoverflow.com/questions/28236390/recyclerview-store-restore-state-between-activities

반응형