RecyclerView.State kullanarak RecyclerView'ın kaydırma konumu nasıl kaydedilir?


Yanıtlar:


37

İle son kaydedilen pozisyonu nasıl kaydetmeyi planlıyorsunuz RecyclerView.State?

Her zaman iyi bir kaydetme durumuna güvenebilirsiniz. Uzatma RecyclerViewve geçersiz kılma onSaveInstanceState () ve 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];
            }
        };
    }

1
şimdi başka bir sorum var, nasıl, hayır, RecyclerView.State ne yapabilir?
陈文涛

4
bu gerçekten çalışıyor mu? Bunu denedim, ancak şu şekilde bir çalışma zamanı istisnası almaya devam ediyorum: MyRecyclerView $ SavedState android.support.v7.widget.RecyclerView $ SavedState
Daivid

2
Geri yükleme örneği durumunda, superState'i süper sınıfına (recytcler görünümü) şu şekilde iletmemiz gerekir: super.onRestoreInstanceState (((ScrollPositionSavingRecyclerView.SavedState) state) .getSuperState ());
micnoy

5
RecyclerView'i genişletirseniz bu işe yaramaz, BadParcelException alırsınız.
EpicPandaForce

1
Bunların hiçbiri gerekli değildir: LinearLayoutManager / GridLayoutManager gibi bir şey kullanırsanız, "kaydırma konumu" sizin için zaten otomatik olarak kaydedilir. (LinearLayoutManager.SavedState'deki mAnchorPosition). Bunu görmüyorsanız, verileri nasıl yeniden uyguladığınızla ilgili bir sorun var demektir.
Brian Yencho

230

Güncelleme

İtibaren recyclerview:1.2.0-alpha02serbestStateRestorationPolicy tanıtılmıştır. Verilen soruna daha iyi bir yaklaşım olabilir.

Bu konu, Android geliştiricileri orta makalesinde ele alınmıştır .

Ayrıca @ rubén-viguera, aşağıdaki yanıtta daha fazla ayrıntı paylaştı. https://stackoverflow.com/a/61609823/892500

Eski cevap

LinearLayoutManager kullanıyorsanız, önceden oluşturulmuş kaydetme api linearLayoutManagerInstance.onSaveInstanceState () ve geri yükleme api ile birlikte gelir linearLayoutManagerInstance.onRestoreInstanceState (...)

Bununla, iade edilen parselleri kendi eyaletinize kaydedebilirsiniz. Örneğin,

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

ve kaydettiğiniz durumla geri yükleme konumunu geri yükleyin. Örneğin,

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

Hepsini özetlemek gerekirse, son kodunuz şuna benzeyecek:

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());
}

Düzenleme: LinearLayoutManager'ın bir alt sınıfı olduğundan, aynı apileri GridLayoutManager ile de kullanabilirsiniz. Öneri için teşekkürler @wegsehen.

Düzenleme: Bir arka plan iş parçacığına da veri yüklüyorsanız, oryantasyon değişikliğinden sonra konumun geri yüklenmesi için onPostExecute / onLoadFinished yönteminiz içinde onRestoreInstanceState'e bir çağrı yapmanız gerekeceğini unutmayın, örn.

@Override
protected void onPostExecute(ArrayList<Movie> movies) {
    mLoadingIndicator.setVisibility(View.INVISIBLE);
    if (movies != null) {
        showMoviePosterDataView();
        mDataAdapter.setMovies(movies);
      mRecyclerView.getLayoutManager().onRestoreInstanceState(mSavedRecyclerLayoutState);
        } else {
            showErrorMessage();
        }
    }

21
Açıkça en iyi cevap bu, bu neden kabul edilmiyor? Herhangi bir LayoutManager'ın sadece LinearLayoutManager'a değil, GridLayoutManager'a ve eğer değilse de yanlış bir uygulamaya sahip olduğuna dikkat edin.
Paul Woitaschek

linearLayoutManager.onInstanceState () her zaman null döndürür -> kaynak kodunu kontrol edin. Maalesef çalışmıyor.
luckyhandler

1
RecyclerView, LayoutManager'ın durumunu kendi onSaveInstanceState'e kaydetmiyor mu? Destek kütüphanesinin
v24'üne bakılıyor

3
Bu, tek bir sayfada çalışır, RecyclerViewancak her sayfada bir ViewPagerile varsa değil RecycerView.
Kris B

1
@Ivan, sanırım bir parçada çalışıyor (sadece kontrol edildi), ama içinde değil onCreateView, veri yüklendikten sonra. @ Farmaker cevabına buradan bakın.
CoolMind

81

Mağaza

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

Onarmak

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

ve bu işe yaramazsa, dene

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

Mağazaya koy onPause() ve geri yükleonResume()


Bu çalışır, ancak yeniden ayarlamanız gerekebilir lastFirstVisiblePositioniçin 0restore edildikten sonra. Bu durum, RecyclerViewörneğin bir dosya gezgini uygulamasında farklı verileri yükleyen bir parçanız / etkinliğiniz olduğunda kullanışlıdır .
blueware

Mükemmel! Hem ayrıntılı bir aktiviteden listeye geri dönmeyi hem de ekran döndürmede durumu kaydetmeyi sağlar
Javi

recyclerView'um varsa ne yapmalıyım SwipeRefreshLayout?
Morozov

2
Neden ilk geri yükleme seçeneği çalışmıyor, ikincisi işe yarıyor?
lucidbrot

1
@MehranJalili bir gibi görünüyorRecyclerView
Vlad

22

Liste etkinliğimden uzaklaşırken Recycler View'un kaydırma konumunu kaydetmek ve ardından geri gitmek için geri düğmesini tıklatmak istedim. Bu sorun için sağlanan çözümlerin çoğu ya gerekenden çok daha karmaşıktı ya da yapılandırmam için işe yaramadı, bu yüzden çözümümü paylaşacağımı düşündüm.

Öncelikle örnek durumunuzu birçoklarının gösterdiği gibi onPause'a kaydedin. Sanırım burada onSaveInstanceState'in bu sürümünün RecyclerView.LayoutManager sınıfından bir yöntem olduğunu vurgulamaya değer.

private LinearLayoutManager mLayoutManager;
Parcelable state;

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

Bunun düzgün çalışmasını sağlamanın anahtarı, bazılarının diğer iş parçacıklarında da belirttiği gibi, bağdaştırıcınızı taktıktan sonra onRestoreInstanceState'i çağırdığınızdan emin olmaktır. Ancak gerçek yöntem çağrısı, birçoklarının belirttiğinden çok daha basittir.

private void someMethod() {
    mVenueRecyclerView.setAdapter(mVenueAdapter);
    mLayoutManager.onRestoreInstanceState(state);
}

1
Doğru çözüm bu. : D
Afjalur Rahman Rana

1
benim için onSaveInstanceState çağrılmaz, bu nedenle onPause'da kaydetme durumu daha iyi bir seçenek gibi görünüyor. im ayrıca parçaya geri dönmek için arka istifi patlatıyor.
filthy_wizard

durumdaki yük için. onViewCreated'da yaptığım. sadece hata ayıklama modundayken ve kesme noktaları kullandığınızda çalışıyor gibi görünüyor? veya bir gecikme eklersem ve yürütmeyi bir koroutine koyarsam.
filthy_wizard

21

I değişkenleri onCreate () içinde ayarlayın, kaydırma konumunu onPause () içinde kaydedin ve onResume () içinde kaydırma konumunu ayarlayın

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

Öğenin ofsetini de koruyun. Güzel. Teşekkürler!
t0m


14

Destek kitaplığında bulunan tüm düzen yöneticileri, kaydırma konumunu nasıl kaydedip geri yükleyeceğini zaten biliyor.

Kaydırma konumu, aşağıdaki koşullar karşılandığında gerçekleşen ilk düzen geçişinde geri yüklenir:

  • bir yerleşim yöneticisi eklenmiştir RecyclerView
  • bir adaptör takılı RecyclerView

Tipik olarak, düzen yöneticisini XML'de ayarlarsınız, böylece artık tek yapmanız gereken

  1. Bağdaştırıcıya veri yükleyin
  2. Ardından adaptörü prize takın.RecyclerView

Bunu istediğiniz zaman yapabilirsiniz, bunlarla sınırlı değildir Fragment.onCreateViewveyaActivity.onCreate .

Örnek: Veriler her güncellendiğinde adaptörün takılı olduğundan emin olun.

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
    }
}

Kaydedilen kaydırma konumu aşağıdaki verilerden hesaplanır:

  • Ekrandaki ilk öğenin adaptör konumu
  • Listenin üstünden öğenin üst kısmının piksel uzaklığı (dikey düzen için)

Bu nedenle, örneğin öğelerinizin dikey ve yatay yönde farklı boyutları varsa, hafif bir uyumsuzluk bekleyebilirsiniz.


RecyclerView/ ScrollView/ Bir olması gerekir ne olursa olsun android:idonun devlet için kaydedilecek.


Bu benim içindi. Bağdaştırıcıyı başlangıçta ayarlıyordum, ardından mevcut olduğunda verilerini güncelliyordum. Yukarıda açıklandığı gibi, verileri kullanılabilir olana kadar bırakmak, verilerin otomatik olarak bulunduğu yere geri kaydırılmasını sağlar.
NeilS

Teşekkürler @ Eugene. LayoutManager'ın kaydırma konumunu kaydetme ve geri yükleme ile ilgili herhangi bir belge var mı?
Adam Hurwitz

@AdamHurwitz Ne tür belgeler bekliyorsunuz? Açıkladığım şey, LinearLayoutManager'ın bir uygulama detayıdır, bu yüzden kaynak kodunu okuyun.
Eugen Pechanec

1
İşte bir bağlantı LinearLayoutManager.SavedState: cs.android.com/androidx/platform/frameworks/support/+/…
Eugen Pechanec

Teşekkürler @EugenPechanec. Bu, cihaz rotasyonları için benim için çalıştı. Ayrıca bir alt gezinme görünümü kullanıyorum ve başka bir alt sekmeye geçip geri döndüğümde liste yeniden baştan başlıyor. Bunun neden olduğuna dair bir fikriniz var mı?
schv09

4

İşte onları kurtarmak ve geri dönüştürücünün durumunu bir parça halinde sürdürmek için Benim Yaklaşımım. İlk olarak, aşağıdaki kod gibi ana etkinliğinize yapılandırma değişiklikleri ekleyin.

android:configChanges="orientation|screenSize"

Daha sonra Parçanızda bu örnek yöntemlerin

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

@OnPause yönteminize aşağıdaki kodu ekleyin

@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);
}

OnConfigartionChanged Yöntemi aşağıdaki gibi ekleyin.

@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);
}

Bu yaklaşım, sorununuzu çözecektir. Farklı bir düzen yöneticiniz varsa, sadece üst düzen yöneticisini değiştirin.


Kalıcı veriler için bir İşleyiciye ihtiyacınız olmayabilir. Yaşam döngüsü yöntemleri, kaydetme / yükleme için yeterli olacaktır.
Mahi

@sayaMahi Doğru bir şekilde tarif edebilir misiniz? Ayrıca onConfigurationChanged'in destroy yöntemini çağırmayı engellediğini gördüm. bu yüzden uygun bir çözüm değil.
Pawan kumar sharma

3

AsyncTaskLoader ile internetten verileri yeniden yüklemeniz gerektiğinde GridLayoutManager ile RecyclerView konumunu bu şekilde geri yüklerim.

Parcelable ve GridLayoutManager'ın global bir değişkenini ve statik bir final dizesi oluşturun:

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

GridLayoutManager durumunu onSaveInstance () içine kaydet

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

OnRestoreInstanceState içinde geri yükle

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

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

Ardından, yükleyici internetten veri aldığında, onLoadFinished () içinde geri dönüşüm görünümü konumunu geri yüklersiniz.

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

.. elbette onCreate içinde gridLayoutManager'ı somutlaştırmanız gerekir. Şerefe


3

Ben de aynı gereksinime sahiptim, ancak buradaki çözümler recyclerView için veri kaynağı nedeniyle beni tam olarak aşamadı.

RecyclerViews 'LinearLayoutManager durumunu onPause () konumunda çıkarıyordum

private Parcelable state;

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

Parcelable state, içine kaydedilir onSaveInstanceState(Bundle outState)ve yeniden çıkarılır onCreate(Bundle savedInstanceState).savedInstanceState != null .

Ancak, recyclerView bağdaştırıcısı bir Oda veritabanına DAO çağrısı tarafından döndürülen ViewModel LiveData nesnesi tarafından doldurulur ve güncellenir.

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

Sonunda, veri bağdaştırıcıda ayarlandıktan hemen sonra örnek durumunu geri yüklemenin kaydırma durumunu döndürmeler arasında koruyacağını buldum.

Bunun da nedeni LinearLayoutManager veri veritabanı çağrısı tarafından döndürüldüğünde geri yüklediğim durumun üzerine yazıldığından ya da geri yüklenen durumun 'boş' bir LinearLayoutManager'a karşı anlamsız olduğundan şüpheleniyorum.

Adaptör verileri doğrudan mevcutsa (yani bir veritabanı çağrısında bitişik değilse), LinearLayoutManager'da örnek durumunun geri yüklenmesi adaptör recyclerView'da ayarlandıktan sonra yapılabilir.

İki senaryo arasındaki ayrım beni yıllarca ayakta tuttu.


3

Android API Seviye 28, ben sadece ben Setimden sağlamak LinearLayoutManagerve RecyclerView.Adapterbenim de Fragment#onCreateView️ ™ yönteminin ve her şey sadece çalıştı. Hiç yapmam onSaveInstanceStateya da onRestoreInstanceStateçalışmam gerekmedi .

Eugen Pechanec'in cevabı bunun neden işe yaradığını açıklıyor.


2

Androidx recyclerView kitaplığının 1.2.0-alpha02 sürümünden başlayarak, artık otomatik olarak yönetiliyor. Şununla ekleyin:

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

Ve kullan:

adapter.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY

StateRestorationPolicy numaralandırmasının 3 seçeneği vardır:

  • İZİN VER - bir sonraki düzen geçişinde RecyclerView durumunu hemen geri yükleyen varsayılan durum
  • PREVENT_WHEN_EMPTY - RecyclerView durumunu yalnızca adaptör boş olmadığında geri yükler (adaptor.getItemCount ()> 0). Verileriniz eşzamansız olarak yüklendiyse, RecyclerView veriler yüklenene kadar bekler ve yalnızca o zaman durum geri yüklenir. Bağdaştırıcınızın bir parçası olarak başlıklar veya yükleme ilerleme göstergeleri gibi varsayılan öğeleriniz varsa, varsayılan öğeler MergeAdapter kullanılarak eklenmedikçe ÖNLEME seçeneğini kullanmalısınız . MergeAdapter tüm bağdaştırıcılarının hazır olmasını bekler ve ancak o zaman durumu geri yükler.
  • ÖNLEME - siz ALLOW veya PREVENT_WHEN_EMPTY ayarını yapana kadar tüm durum geri yüklemesi ertelenir.

Bu cevabın verildiği sırada recyclerView kitaplığının hala alpha03'te olduğunu, ancak alfa aşamasının üretim amaçları için uygun olmadığını unutmayın .


Çok fazla çalışma tasarrufu sağlandı. Aksi takdirde, liste tıklama dizinini kaydetmemiz, öğeleri geri yüklememiz, onCreateView'de yeniden çizmeyi engellememiz, scrollToPosition uygulamamız (veya diğer yanıtları uygulamanız) gerekiyordu ve yine de kullanıcı, geri döndükten sonra farkı fark edebiliyordu
Rahul Kahale

Ayrıca, uygulama üzerinden navigasyondan sonra RecyclerView konumunu kaydetmek istersem ... bunun için bir araç var mı?
StayCool

@RubenViguera Alpha neden üretim amaçlı değil? Yani bu gerçekten kötü mü?
StayCool

1

Benim için sorun, adaptörümü her değiştirdiğimde recyclerView'da que scroll konumunu kaybederek yeni bir layoutmanager kurmamdı.


1

RecyclerView ile son karşılaştığım çıkmazı paylaşmak istiyorum. Umarım aynı sorunu yaşayan herkes fayda sağlar.

Proje Gereksinimim: Bu nedenle, Ana Aktivitemdeki (Aktivite-A) bazı tıklanabilir öğeleri listeleyen bir RecyclerView var. Kalem tıklandığında, Kalem Detayları (Aktivite-B) ile birlikte yeni bir Aktivite gösterilir.

Manifest'te uyguladım dosyasına Activity-A'nın Activity-B'nin üst öğesi olduğunu ekledim, bu şekilde Activity-B'nin ActionBar'ında bir geri veya home düğmesi var

Sorun: Activity-B ActionBar'da Back veya Home düğmesine her bastığımda Activity-A, onCreate () 'den başlayarak tam Activity Life Cycle'a giriyor

RecyclerView Bağdaştırıcısının Listesini kaydederek bir onSaveInstanceState () uygulamama rağmen, Activity-A yaşam döngüsünü başlattığında, saveInstanceState onCreate () yönteminde her zaman boştur.

İnternette daha fazla araştırma yaparken aynı problemle karşılaştım ancak kişi Anroid cihazının altındaki Geri veya Ana Sayfa düğmesinin (Varsayılan Geri / Ana Sayfa düğmesi) Activity-A'nın Aktivite Yaşam Döngüsüne girmediğini fark etti.

Çözüm:

  1. Etkinlik-B'nin manifestindeki Ana Etkinlik Etiketini kaldırdım
  2. Activity-B'de ana sayfa veya geri düğmesini etkinleştirdim

    OnCreate () yöntemi altında bu satırı ekleyin supportActionBar? .SetDisplayHomeAsUpEnabled (true)

  3. Overide fun onOptionsItemSelected () yönteminde, id'ye göre hangi öğenin tıklandığı item.ItemId öğesini kontrol ettim. Geri düğmesinin kimliği:

    android.R.id.home

    Ardından android.R.id.home içinde bir finish () işlevi çağrısı uygulayın

    Bu, Aktivite-B'yi sona erdirecek ve tüm yaşam döngüsünden geçmeden Acitivy-A'yı getirecektir.

İhtiyacım için bu şimdiye kadar en iyi çözüm.

     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)
}

1

Küçük bir farkla aynı sorunu yaşadım, Veri Bağlama kullanıyordum ve ben recyclerView adaptörü ve bağlayıcı yöntemlerde LayoutManager batıyordu.

Sorun, onResume'dan sonra veri bağlamanın gerçekleşmesiydi, bu yüzden onResume'dan sonra layoutManager'ımı sıfırlıyordu ve bu, her seferinde orijinal yerine geri kaydırıldığı anlamına geliyordu. Databinding Adapter yöntemlerinde layoutManager'ı ayarlamayı bıraktığımda tekrar iyi çalışıyor.


nasıl başardın
Kedar Sukerkar

0

Benim durumumda RecyclerView’ları layoutManagerhem XML’de hem de onViewCreated. Görevi kaldırmak onViewCreatedonu düzeltti.

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

-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();

    }   

Neden kullanıyorum OnSaveInstanceState()içinde onPause()başka bir etkinliğe anahtarı OnPause called.It o kaydırma konumunu kaydetmek ve geri başka bir etkinliğe gelen pozisyonunu geri yükleyecektir olurdu da, aracı.


2
Genel statik alan iyi değil. Küresel veriler ve tekler iyi değil.
weston

@weston Şimdi anladım. Savingstate'i global kaldırmak için onpause olarak değiştirdim.
Steve
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.