मेरी खराब अंग्रेजी के लिए खेद है।RecyclerView की स्क्रॉल सटीक स्थिति को कैसे सहेजना और पुनर्स्थापित करना है?
मुझे सटीक स्थिति चाहिए। और गतिविधि/टुकड़ा के बाद नष्ट (कोई बात नहीं मैं इसे नष्ट या सिस्टम यह नष्ट कर देता है), मैं गतिविधि/टुकड़ा फिर से खोलना कर दिया गया है, RecyclerView
भी ही स्थिति के रूप में के रूप में यह नष्ट कर दिया गया है सकते हैं।
"वही" का मतलब "आइटम स्थिति" नहीं है, क्योंकि शायद आइटम आंशिक रूप से आखिरी बार प्रदर्शित हो सकता है।
मैं वही स्थिति बहाल करना चाहता हूं।
मैंने नीचे कुछ तरीकों का प्रयास किया है, लेकिन कोई भी सही नहीं है।
कोई मदद कर सकता है?
1. पहला तरीका।
स्क्रॉल स्टॉप होने पर स्क्रॉल सटीक स्थिति की गणना करने के लिए onScrolled
का उपयोग करें, स्थिति को सहेजें। जब स्पिनर डेटासेट या टुकड़े को क्रिएट पर परिवर्तित करें, चयनित डेटासेट की स्थिति को पुनर्स्थापित करें। कुछ डेटासेट में कई पंक्तियां हो सकती हैं।
ऐप नष्ट होने के बाद यह सहेज और बहाल कर सकता है, लेकिन शायद बहुत अधिक गणना हो सकती है?
यह
Skipped 60 frames! The application may be doing too much work on its main thread. attempt to finish an input event but the input event receiver has already been disposed. android total arena pages for jit.
कारण होगा और scrollY
विशाल है अगर 111111
, जब खुले टुकड़ा, RecyclerView पहले दिखाएगा सूची पहले आइटम से शुरू करते हैं, और कुछ देर के बाद, यह स्क्रॉल की तरह, scrollY
स्थिति पर।
इसे कोई देरी कैसे नहीं करें?
recyclerView.addOnScrollListener(new OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, final int dy) {
super.onScrolled(recyclerView, dx, dy);
handler.post(new Runnable() {
@Override
public void run() {
if (isTableSwitched) {
scrollY = 0;
isTableSwitched = false;
}
scrollY = scrollY + dy;
Log.i("dy——scrollY——table", String.valueOf(dy) + "——" + String.valueOf(scrollY) + tableName);
}
});
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
saveRecyclerPosition(tableName, scrollY);
break;
case RecyclerView.SCROLL_STATE_DRAGGING:
break;
case RecyclerView.SCROLL_STATE_SETTLING:
break;
}
}
});
public void saveRecyclerPosition(String tableName, int y) {
prefEditorSettings.putInt(KEY_SCROLL_Y + tableName, y);
prefEditorSettings.commit();
}
public void restoreRecyclerViewState(final String tableName) {
handler.post(new Runnable() {
@Override
public void run() {
recyclerView.scrollBy(0, prefSettings.getInt(KEY_SCROLL_Y + tableName, 0));
}
});
}
//use Spinner to choose dataset
spnWordbook.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
isTableSwitched = true;
tableName= parent.getItemAtPosition(position).toString();
prefEditorSettings.putString(KEY_SPINNER_SELECTED_TABLENAME, tableName);
prefEditorSettings.commit();
wordsList = WordsManager.getWordsList(tableName);
wordCardAdapter.updateList(wordsList);
restoreRecyclerViewState(tableName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
2.Second रास्ता।
यह पूरी तरह से चलता है, लेकिन यह केवल खंड जीवन चक्र में ही काम कर सकता है।
मैं बचाने के लिए और HashMap
बहाल करने के लिए ObjectOutputStream
और ObjectInputStream
इस्तेमाल करने की कोशिश की, लेकिन यह काम नहीं करता।
इसे स्मृति में कैसे सहेजना है?
private HashMap <String, Parcelable> hmRecyclerViewState = new HashMap<String, Parcelable>();
public void saveRecyclerPosition(String tableName) {
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
hmRecyclerViewState.put(tableName, recyclerViewState);
}
public void restoreRecyclerViewState(final String tableName) {
if (hmRecyclerViewState.get(tableName) != null) {
recyclerViewState = hmRecyclerViewState.get(tableName);
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
recyclerViewState = null;
}
3.Third रास्ता।
मैं दूसरी तरह से बदलने के लिए, HashMap
के बजाय Bundle
उपयोग करें, लेकिन यह एक ही सवाल है, जब टुकड़ा जीवन चक्र से बाहर काम नहीं करता।
मैं manually serialize/deserialize android bundle का उपयोग स्मृति में bundle
को बचाने के लिए, लेकिन जब यह बहाल, यह मान्य bundle
नहीं मिलता है।
============================================== ========================= समाधान
सभी को धन्यवाद!
अंत में मैं इस समस्या का समाधान है, आप इसे my code में देख सकते हैं, बस इन 2 तरीकों देखें: saveRecyclerViewPosition और restoreWordRecyclerViewPosition।
शायद लेआउटमेनगर से पहले प्रदर्शित आइटम आईडी और उसका ऑफसेट प्राप्त करें, फिर आप ऑफ़सेट द्वारा स्क्रॉल को फिर से बनाने और समायोजित करने की स्थिति में स्थानांतरित कर सकते हैं। यदि संभवतः आपका डेटासेट बदल गया तो यह शायद भी काम करेगा। –
@ bleeding182 धन्यवाद। मैंने इस तरह से सोचा है, लेकिन मुझे नहीं पता कि किसी आइटम का ऑफ़सेट कैसे प्राप्त किया जाए? प्रत्येक आइटम की अलग-अलग ऊंचाई – DawnYu
है, आप लेआउटमैनेजर से केवल दृश्य प्राप्त कर सकते हैं, फिर getTop() या getDecoratedTop() प्राप्त करें, उस और recyclerview.top के बीच का अंतर आपका ऑफसेट होगा;) और यहां तक कि अगर आप ऑफसेट नहीं प्राप्त करते हैं ठीक है, आप फ्रेम को छोड़ने के बिना कम से कम सही स्थिति पर होंगे –