Bagaimana cara menyimpan posisi gulir RecyclerView menggunakan RecyclerView.State?

107

Saya punya pertanyaan tentang RecyclerView.State Android .

Saya menggunakan RecyclerView, bagaimana saya bisa menggunakan dan mengikatnya dengan RecyclerView.State?

Tujuan saya adalah untuk menyimpan posisi gulir RecyclerView .

陈文涛
sumber

Jawaban:

37

Bagaimana rencana Anda untuk menyimpan posisi terakhir yang disimpan RecyclerView.State?

Anda selalu bisa mengandalkan keadaan penyelamatan yang baik. Perluas RecyclerViewdan timpa onSaveInstanceState () dan onRestoreInstanceState():

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        LayoutManager layoutManager = getLayoutManager();
        if(layoutManager != null && layoutManager instanceof LinearLayoutManager){
            mScrollPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
        }
        SavedState newState = new SavedState(superState);
        newState.mScrollPosition = mScrollPosition;
        return newState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
        if(state != null && state instanceof SavedState){
            mScrollPosition = ((SavedState) state).mScrollPosition;
            LayoutManager layoutManager = getLayoutManager();
            if(layoutManager != null){
              int count = layoutManager.getItemCount();
              if(mScrollPosition != RecyclerView.NO_POSITION && mScrollPosition < count){
                  layoutManager.scrollToPosition(mScrollPosition);
              }
            }
        }
    }

    static class SavedState extends android.view.View.BaseSavedState {
        public int mScrollPosition;
        SavedState(Parcel in) {
            super(in);
            mScrollPosition = in.readInt();
        }
        SavedState(Parcelable superState) {
            super(superState);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(mScrollPosition);
        }
        public static final Parcelable.Creator<SavedState> CREATOR
                = new Parcelable.Creator<SavedState>() {
            @Override
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
Nikola Despotoski
sumber
1
sekarang saya punya pertanyaan lain, bagaimana, tidak, apa yang bisa dilakukan RecyclerView.State?
陈文涛
4
apakah ini benar-benar berhasil? Saya telah mencoba ini, tetapi saya tetap mendapatkan pengecualian waktu proses seperti ini: MyRecyclerView $ SavedState tidak dapat dilemparkan ke android.support.v7.widget.RecyclerView $ SavedState
Daivid
2
Pada status instance pemulihan kita perlu meneruskan superState ke kelas supernya (tampilan recytcler) seperti ini: super.onRestoreInstanceState (((ScrollPositionSavingRecyclerView.SavedState) state) .getSuperState ());
micnoy
5
Ini tidak berfungsi jika Anda memperluas RecyclerView, Anda akan mendapatkan BadParcelException.
EpicPandaForce
1
Semua ini tidak diperlukan: jika Anda menggunakan sesuatu seperti LinearLayoutManager / GridLayoutManager, "posisi gulir" sudah disimpan secara otomatis untuk Anda. (Ini adalah mAnchorPosition di LinearLayoutManager.SavedState). Jika Anda tidak melihatnya, maka ada yang salah dengan cara Anda menerapkan ulang data.
Brian Yencho
229

Memperbarui

Mulai dari recyclerview:1.2.0-alpha02rilis StateRestorationPolicytelah diperkenalkan. Ini bisa menjadi pendekatan yang lebih baik untuk masalah yang diberikan.

Topik ini telah dibahas pada artikel medium pengembang android .

Juga, @ rubén-viguera membagikan lebih banyak detail dalam jawaban di bawah ini. https://stackoverflow.com/a/61609823/892500

Jawaban lama

Jika Anda menggunakan LinearLayoutManager, LinearLayoutManager dilengkapi dengan save api linearLayoutManagerInstance.onSaveInstanceState () dan pulihkan api linearLayoutManagerInstance.onRestoreInstanceState (...)

Dengan itu, Anda dapat menyimpan parsel yang dikembalikan ke negara bagian Anda. misalnya,

outState.putParcelable("KeyForLayoutManagerState", linearLayoutManagerInstance.onSaveInstanceState());

, dan pulihkan posisi pemulihan dengan keadaan yang Anda simpan. misalnya,

Parcelable state = savedInstanceState.getParcelable("KeyForLayoutManagerState");
linearLayoutManagerInstance.onRestoreInstanceState(state);

Untuk menyelesaikan semuanya, kode akhir Anda akan terlihat seperti ini

private static final String BUNDLE_RECYCLER_LAYOUT = "classname.recycler.layout";

/**
 * This is a method for Fragment. 
 * You can do the same in onCreate or onRestoreInstanceState
 */
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);

    if(savedInstanceState != null)
    {
        Parcelable savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
        recyclerView.getLayoutManager().onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, recyclerView.getLayoutManager().onSaveInstanceState());
}

Edit: Anda juga dapat menggunakan apis yang sama dengan GridLayoutManager, karena ini adalah subclass dari LinearLayoutManager. Terima kasih @wegsehen atas sarannya.

Edit: Ingat, jika Anda juga memuat data di thread latar belakang, Anda perlu memanggil onRestoreInstanceState dalam metode onPostExecute / onLoadFinished Anda agar posisi dipulihkan setelah orientasi berubah, mis.

@Override
protected void onPostExecute(ArrayList<Movie> movies) {
    mLoadingIndicator.setVisibility(View.INVISIBLE);
    if (movies != null) {
        showMoviePosterDataView();
        mDataAdapter.setMovies(movies);
      mRecyclerView.getLayoutManager().onRestoreInstanceState(mSavedRecyclerLayoutState);
        } else {
            showErrorMessage();
        }
    }
Gökhan Barış Aker
sumber
21
Ini jelas merupakan jawaban terbaik, mengapa ini tidak diterima? Perhatikan bahwa setiap LayoutManager memiliki itu, tidak hanya LinearLayoutManager, juga GridLayoutManager, dan jika bukan implementasi yang salah.
Paul Woitaschek
linearLayoutManager.onInstanceState () selalu mengembalikan null -> periksa kode sumbernya. Sayangnya tidak berfungsi.
luckyhandler
1
Bukankah RecyclerView melakukan penyimpanan status LayoutManager-nya di onSaveInstanceState-nya sendiri? Melihat v24 dari dukungan lib ...
androidguy
3
Ini berfungsi pada satu RecyclerViewtetapi tidak jika Anda memiliki ViewPagerdengan a RecycerViewdi setiap halaman.
Kris B
1
@Ivan, saya pikir ini bekerja dalam sebuah fragmen (baru saja dicentang), tetapi tidak dalam onCreateView, tetapi setelah memuat data. Lihat jawaban @Farmaker di sini.
CoolMind
81

Toko

lastFirstVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

Mengembalikan

((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition);

dan jika itu tidak berhasil, coba

((LinearLayoutManager) rv.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0)

Simpan onPause() dan pulihkanonResume()

Gillis Haasnoot
sumber
Ini berfungsi, tetapi Anda mungkin perlu mengatur ulang lastFirstVisiblePositionke 0setelah memulihkannya. Kasus ini berguna jika Anda memiliki fragmen / aktivitas yang memuat data berbeda dalam satu RecyclerView, misalnya, aplikasi file explorer.
blueware
Luar biasa! Ini memuaskan baik kembali dari aktivitas detail ke daftar, dan menyimpan status pada rotasi layar
Javi
apa yang harus dilakukan jika recyclerView saya ada SwipeRefreshLayout?
Morozov
2
Mengapa opsi pemulihan pertama tidak berfungsi, tetapi yang kedua berfungsi?
lucidbrot
1
@MehranJalili tampaknya menjadiRecyclerView
Vlad
22

Saya ingin menyimpan posisi gulir Recycler View saat menavigasi keluar dari aktivitas daftar saya, lalu mengklik tombol kembali untuk menavigasi kembali. Banyak solusi yang disediakan untuk masalah ini jauh lebih rumit daripada yang dibutuhkan atau tidak berfungsi untuk konfigurasi saya, jadi saya pikir saya akan membagikan solusi saya.

Pertama-tama simpan status instance Anda di onPause seperti yang telah ditunjukkan banyak orang. Saya pikir perlu ditekankan di sini bahwa versi onSaveInstanceState ini adalah metode dari kelas RecyclerView.LayoutManager.

private LinearLayoutManager mLayoutManager;
Parcelable state;

        @Override
        public void onPause() {
            super.onPause();
            state = mLayoutManager.onSaveInstanceState();
        }

Kunci agar ini berfungsi dengan benar adalah memastikan Anda memanggil onRestoreInstanceState setelah Anda memasang adaptor, seperti yang ditunjukkan beberapa di utas lain. Namun panggilan metode sebenarnya jauh lebih sederhana daripada yang telah ditunjukkan banyak orang.

private void someMethod() {
    mVenueRecyclerView.setAdapter(mVenueAdapter);
    mLayoutManager.onRestoreInstanceState(state);
}
Braden Holt
sumber
1
Itulah solusi jitu. : D
Afjalur Rahman Rana
1
bagi saya onSaveInstanceState tidak disebut sehingga status penyimpanan di onPause sepertinya merupakan opsi yang lebih baik. im juga memunculkan backstack untuk kembali ke fragmen.
filthy_wizard
untuk beban di negara bagian. yang saya lakukan di onViewCreated. sepertinya hanya bekerja ketika im dalam mode debug dan menggunakan break point? atau jika saya menambahkan penundaan dan menjalankan eksekusi di coroutine.
filthy_wizard
21

Saya mengatur variabel di onCreate (), menyimpan posisi gulir di onPause () dan mengatur posisi gulir di onResume ()

public static int index = -1;
public static int top = -1;
LinearLayoutManager mLayoutManager;

@Override
public void onCreate(Bundle savedInstanceState)
{
    //Set Variables
    super.onCreate(savedInstanceState);
    cRecyclerView = ( RecyclerView )findViewById(R.id.conv_recycler);
    mLayoutManager = new LinearLayoutManager(this);
    cRecyclerView.setHasFixedSize(true);
    cRecyclerView.setLayoutManager(mLayoutManager);

}

@Override
public void onPause()
{
    super.onPause();
    //read current recyclerview position
    index = mLayoutManager.findFirstVisibleItemPosition();
    View v = cRecyclerView.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - cRecyclerView.getPaddingTop());
}

@Override
public void onResume()
{
    super.onResume();
    //set recyclerview position
    if(index != -1)
    {
        mLayoutManager.scrollToPositionWithOffset( index, top);
    }
}
farhad.kargaran
sumber
Pertahankan offset item juga. Bagus. Terima kasih!
t0m
14

Anda tidak perlu lagi menyimpan dan memulihkan keadaan sendiri. Jika Anda menyetel ID unik di xml dan recyclerView.setSaveEnabled (true) (true secara default), sistem akan otomatis melakukannya. Berikut lebih lanjut tentang ini: http://trickyandroid.com/saving-android-view-state-correctly/

AppiDevo
sumber
14

Semua manajer tata letak yang dibundel di pustaka dukungan sudah tahu cara menyimpan dan memulihkan posisi gulir.

Posisi gulir dipulihkan pada tata letak pertama yang terjadi ketika kondisi berikut terpenuhi:

  • manajer tata letak dilampirkan ke RecyclerView
  • adaptor terpasang ke RecyclerView

Biasanya Anda menyetel pengelola tata letak dalam XML sehingga yang harus Anda lakukan sekarang adalah

  1. Muat adaptor dengan data
  2. Kemudian pasang adaptor keRecyclerView

Anda dapat melakukan ini kapan saja, tidak dibatasi Fragment.onCreateViewatau Activity.onCreate.

Contoh: Pastikan adaptor terpasang setiap kali data diperbarui.

viewModel.liveData.observe(this) {
    // Load adapter.
    adapter.data = it

    if (list.adapter != adapter) {
        // Only set the adapter if we didn't do it already.
        list.adapter = adapter
    }
}

Posisi gulir yang disimpan dihitung dari data berikut:

  • Posisi adaptor item pertama di layar
  • Pengimbangan piksel di bagian atas item dari atas daftar (untuk tata letak vertikal)

Oleh karena itu, Anda dapat mengharapkan sedikit ketidakcocokan, misalnya jika item Anda memiliki dimensi berbeda dalam orientasi potret dan lanskap.


The RecyclerView/ ScrollView/ apapun perlu memiliki android:idbagi negara untuk diselamatkan.

Eugen Pechanec
sumber
Ini untukku. Saya mengatur adaptor pada awalnya kemudian memperbarui datanya jika tersedia. Seperti dijelaskan di atas, membiarkannya hingga data tersedia membuatnya secara otomatis menggulir kembali ke tempatnya.
NeilS
Terima kasih @Eugen. Apakah ada dokumentasi tentang penyimpanan dan pemulihan posisi gulir LayoutManager?
Adam Hurwitz
@AdamHurwitz Dokumentasi seperti apa yang Anda harapkan? Yang saya jelaskan adalah detail implementasi LinearLayoutManager, jadi baca kode sumbernya.
Eugen Pechanec
1
Ini tautan ke LinearLayoutManager.SavedState: cs.android.com/androidx/platform/frameworks/support/+/…
Eugen Pechanec
Terima kasih, @EugenPechanec. Ini berfungsi untuk saya untuk rotasi perangkat. Saya juga menggunakan tampilan navigasi bawah dan ketika saya beralih ke tab bawah lain dan kembali, daftar tersebut dimulai dari awal lagi. Ada ide mengapa ini terjadi?
schv09
4

Berikut adalah Pendekatan saya untuk menyimpannya dan mempertahankan status recyclerview dalam sebuah fragmen. Pertama, tambahkan perubahan konfigurasi pada aktivitas induk Anda seperti kode di bawah ini.

android:configChanges="orientation|screenSize"

Kemudian di Fragmen Anda, deklarasikan metode instance ini

private  Bundle mBundleRecyclerViewState;
private Parcelable mListState = null;
private LinearLayoutManager mLinearLayoutManager;

Tambahkan kode di bawah ini dalam metode @onPause Anda

@Override
public void onPause() {
    super.onPause();
    //This used to store the state of recycler view
    mBundleRecyclerViewState = new Bundle();
    mListState =mTrailersRecyclerView.getLayoutManager().onSaveInstanceState();
    mBundleRecyclerViewState.putParcelable(getResources().getString(R.string.recycler_scroll_position_key), mListState);
}

Tambahkan Metode onConfigartionChanged seperti di bawah ini.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //When orientation is changed then grid column count is also changed so get every time
    Log.e(TAG, "onConfigurationChanged: " );
    if (mBundleRecyclerViewState != null) {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                mListState = mBundleRecyclerViewState.getParcelable(getResources().getString(R.string.recycler_scroll_position_key));
                mTrailersRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);

            }
        }, 50);
    }
    mTrailersRecyclerView.setLayoutManager(mLinearLayoutManager);
}

Pendekatan ini akan menyelesaikan masalah Anda. jika Anda memiliki pengelola tata letak yang berbeda, maka ganti saja pengelola tata letak atas.

Pawan kumar sharma
sumber
Anda mungkin tidak membutuhkan Handler untuk menyimpan data. Metode siklus hidup akan cukup untuk menyimpan / memuat.
Mahi
@sayaMahi Bisakah Anda menjelaskan dengan cara yang tepat. Saya juga telah melihat bahwa onConfigurationChanged mencegah untuk memanggil metode penghancuran. jadi ini bukan solusi yang tepat.
Pawan kumar sharma
3

Ini adalah cara saya mengembalikan posisi RecyclerView dengan GridLayoutManager setelah rotasi ketika Anda perlu memuat ulang data dari internet dengan AsyncTaskLoader.

Buat variabel global Parcelable dan GridLayoutManager dan string final statis:

private Parcelable savedRecyclerLayoutState;
private GridLayoutManager mGridLayoutManager;
private static final String BUNDLE_RECYCLER_LAYOUT = "recycler_layout";

Simpan status gridLayoutManager di onSaveInstance ()

 @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, 
            mGridLayoutManager.onSaveInstanceState());
        }

Pulihkan di onRestoreInstanceState

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        //restore recycler view at same position
        if (savedInstanceState != null) {
            savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
        }
    }

Kemudian saat loader mengambil data dari internet, Anda mengembalikan posisi recyclerview di onLoadFinished ()

if(savedRecyclerLayoutState!=null){
                mGridLayoutManager.onRestoreInstanceState(savedRecyclerLayoutState);
            }

..tentu saja Anda harus membuat instance gridLayoutManager di dalam onCreate. Bersulang

Petani
sumber
3

Saya memiliki persyaratan yang sama, tetapi solusi di sini tidak cukup membantu saya, karena sumber data untuk recyclerView.

Saya mengekstrak status LinearLayoutManager RecyclerViews di onPause ()

private Parcelable state;

Public void onPause() {
    state = mLinearLayoutManager.onSaveInstanceState();
}

Parcelable statedisimpan di onSaveInstanceState(Bundle outState), dan diekstraksi lagi di onCreate(Bundle savedInstanceState), saat savedInstanceState != null.

Namun, adaptor recyclerView diisi dan diperbarui oleh objek ViewModel LiveData yang ditampilkan oleh panggilan DAO ke database Room.

mViewModel.getAllDataToDisplay(mSelectedData).observe(this, new Observer<List<String>>() {
    @Override
    public void onChanged(@Nullable final List<String> displayStrings) {
        mAdapter.swapData(displayStrings);
        mLinearLayoutManager.onRestoreInstanceState(state);
    }
});

Saya akhirnya menemukan bahwa memulihkan status instance langsung setelah data disetel di adaptor akan menjaga status gulir di seluruh rotasi.

Saya menduga ini baik karena LinearLayoutManagerstatus yang saya pulihkan telah ditimpa ketika data dikembalikan oleh panggilan database, atau status yang dipulihkan tidak berarti terhadap LinearLayoutManager 'kosong'.

Jika data adaptor tersedia secara langsung (misalnya, tidak terkait pada panggilan database), maka memulihkan status instance di LinearLayoutManager bisa dilakukan setelah adaptor disetel pada recyclerView.

Perbedaan antara kedua skenario tersebut membuat saya bertahan lama.

MikeP
sumber
3

Di Android API Level 28, saya cukup memastikan bahwa saya menyiapkan LinearLayoutManagerdan RecyclerView.Adapterdalam Fragment#onCreateViewmetode saya , dan semuanya Just Worked ™ ️. Saya tidak perlu melakukan apa pun onSaveInstanceStateatau onRestoreInstanceStatebekerja.

Jawaban Eugen Pechanec menjelaskan mengapa ini berhasil.

Heath Borders
sumber
2

Mulai dari versi 1.2.0-alpha02 library androidx recyclerView, sekarang dikelola secara otomatis. Tambahkan saja dengan:

implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02"

Dan gunakan:

adapter.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY

Enum StateRestorationPolicy memiliki 3 opsi:

  • ALLOW - status default, yang segera memulihkan status RecyclerView, di pas tata letak berikutnya
  • PREVENT_WHEN_EMPTY - memulihkan status RecyclerView hanya jika adaptor tidak kosong (adapter.getItemCount ()> 0). Jika data Anda dimuat secara asinkron, RecyclerView menunggu hingga data dimuat dan baru kemudian statusnya dipulihkan. Jika Anda memiliki item default, seperti header atau memuat indikator kemajuan sebagai bagian dari Adapter Anda, maka Anda harus menggunakan opsi PREVENT , kecuali item default ditambahkan menggunakan MergeAdapter . MergeAdapter menunggu hingga semua adaptornya siap dan baru setelah itu memulihkan status.
  • PREVENT - semua pemulihan status ditangguhkan hingga Anda menyetel ALLOW atau PREVENT_WHEN_EMPTY.

Perhatikan bahwa pada saat jawaban ini, pustaka recyclerView masih dalam alpha03, tetapi fase alfa tidak cocok untuk tujuan produksi .

Rubén Viguera
sumber
Begitu banyak kerja paksa yang disimpan. Jika tidak, kami harus menyimpan indeks klik daftar, memulihkan elemen, mencegah penggambaran ulang di onCreateView, menerapkan scrollToPosition (atau lakukan sebagai jawaban lain), namun pengguna dapat melihat perbedaannya setelah kembali
Rahul Kahale
Juga, Jika saya ingin menyimpan posisi RecyclerView setelah navigasi melalui aplikasi ... apakah ada alat untuk itu?
StayCool
@RubenViguera Mengapa alpha bukan untuk tujuan produksi? Maksud saya apakah itu benar-benar buruk?
StayCool
1

Bagi saya, masalahnya adalah saya menyiapkan layoutmanager baru setiap kali saya mengganti adaptor saya, kehilangan posisi gulir antrean di recyclerView.

Ronaldo Albertini
sumber
1

Saya hanya ingin berbagi masalah yang baru-baru ini saya hadapi dengan RecyclerView. Saya berharap siapa pun yang mengalami masalah yang sama akan mendapat manfaat.

Persyaratan Proyek Saya: Jadi saya memiliki RecyclerView yang mencantumkan beberapa item yang dapat diklik di Aktivitas Utama saya (Aktivitas-A). Saat Item diklik, Aktivitas baru ditampilkan dengan Detail Item (Aktivitas-B).

Saya mengimplementasikan dalam file Manifest bahwa Activity-A adalah induk dari Activity-B, dengan begitu, saya memiliki tombol kembali atau home pada ActionBar dari Activity-B

Masalah: Setiap kali saya menekan tombol Back atau Home di Activity-B ActionBar, Activity-A masuk ke Activity Life Cycle penuh mulai dari onCreate ()

Meskipun saya mengimplementasikan onSaveInstanceState () yang menyimpan Daftar Adaptor RecyclerView, ketika Activity-A memulai siklus hidupnya, saveInstanceState selalu nol dalam metode onCreate ().

Menggali lebih lanjut di internet, saya menemukan masalah yang sama tetapi orang tersebut memperhatikan bahwa tombol Kembali atau Beranda di bawah perangkat Anroid (tombol Kembali / Beranda Default), Aktivitas-A tidak masuk ke Siklus Hidup Aktivitas.

Larutan:

  1. Saya menghapus Tag untuk Aktivitas Induk di manifes untuk Aktivitas-B
  2. Saya mengaktifkan tombol beranda atau kembali pada Aktivitas-B

    Di bawah metode onCreate () tambahkan baris ini supportActionBar? .SetDisplayHomeAsUpEnabled (true)

  3. Dalam metode onOptionsItemSelected () overide fun, saya memeriksa item.ItemId di mana item diklik berdasarkan id. Id untuk tombol kembali adalah

    android.R.id.home

    Kemudian implementasikan panggilan fungsi finish () di dalam android.R.id.home

    Ini akan mengakhiri Aktivitas-B dan membawa Aktivitas-A tanpa melalui seluruh siklus hidup.

Untuk kebutuhan saya, sejauh ini ini adalah solusi terbaik.

     override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_show_project)

    supportActionBar?.title = projectName
    supportActionBar?.setDisplayHomeAsUpEnabled(true)

}


 override fun onOptionsItemSelected(item: MenuItem?): Boolean {

    when(item?.itemId){

        android.R.id.home -> {
            finish()
        }
    }

    return super.onOptionsItemSelected(item)
}
Andy Parinas
sumber
1

Saya memiliki masalah yang sama dengan perbedaan kecil, saya menggunakan Databinding , dan saya menyetel adaptor recyclerView dan layoutManager dalam metode binding.

Masalahnya adalah pengikatan data terjadi setelah onResume jadi itu menyetel ulang layoutManager saya setelah onResume dan itu berarti itu menggulir kembali ke tempat semula setiap waktu. Jadi, ketika saya berhenti menyetel layoutManager dalam metode adaptor Databinding, itu berfungsi dengan baik lagi.

Amin Keshavarzian
sumber
bagaimana Anda mencapainya?
Kedar Sukerkar
0

Dalam kasus saya, saya menyetel RecyclerView layoutManagerdalam XML dan dalam onViewCreated. Menghapus tugas di onViewCreatedmemperbaikinya.

with(_binding.list) {
//  layoutManager =  LinearLayoutManager(context)
    adapter = MyAdapter().apply {
        listViewModel.data.observe(viewLifecycleOwner,
            Observer {
                it?.let { setItems(it) }
            })
    }
}
maxbeaudoin.dll
sumber
-1

Activity.java:

public RecyclerView.LayoutManager mLayoutManager;

Parcelable state;

    mLayoutManager = new LinearLayoutManager(this);


// Inside `onCreate()` lifecycle method, put the below code :

    if(state != null) {
    mLayoutManager.onRestoreInstanceState(state);

    } 

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

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

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

        state = mLayoutManager.onSaveInstanceState();

    }   

Why I'm using OnSaveInstanceState()in onPause()means, While beralih ke aktivitas lain onPause akan dipanggil. Ini akan menyimpan posisi gulir itu dan memulihkan posisi saat kita kembali dari aktivitas lain.

Steve
sumber
2
Bidang statis publik tidak bagus. Data global dan lajang tidak bagus.
barat
@weston Saya mengerti sekarang. Saya mengubah savingstate menjadi onpause untuk menghapus global.
Steve