পুনর্ব্যবহারযোগ্য ভিউ: অসঙ্গতি সনাক্ত হয়েছে। অবৈধ আইটেমের অবস্থান


271

আমাদের কিউএ একটি ত্রুটি সনাক্ত করেছে: অ্যান্ড্রয়েড ডিভাইস (ড্রয়েড টার্বো) ঘোরানোর সময়, নিম্নলিখিত রিসাইক্লারভিউ-সম্পর্কিত ক্র্যাশ ঘটেছিল:

java.lang.IndexOutOfBoundsException: অসঙ্গতি ধরা পড়ে। অবৈধ আইটেম অবস্থান 2 (অফসেট: 2) .সেটেট: 3

আমার কাছে এটি রিসাইক্লভিউয়ের অভ্যন্তরীণ ত্রুটির মতো দেখায়, যেহেতু আমরা সরাসরি আমাদের কোডের দ্বারা সৃষ্ট এর কোনও উপায় সম্পর্কে ভাবতে পারি না ...

কেউ কি এই সমস্যার মুখোমুখি হয়েছেন?

এর সমাধান কী হবে?

একটি নৃশংস পরিশ্রম হতে পারে যখন ব্যতিক্রমটি ঘটে তখন এটি ধরা পড়ে এবং স্ক্র্যাচ থেকে পুনর্ব্যবহারযোগ্য দৃষ্টান্তটি পুনরায় তৈরি করে, যাতে কোনও দুর্নীতিগ্রস্থ অবস্থার হাতছাড়া না হয়।

তবে, সম্ভব হলে আমি সমস্যাটি মাস্কিংয়ের পরিবর্তে সমস্যাটি আরও ভালভাবে বুঝতে (এবং সম্ভবত এটির উত্স থেকে এটি ঠিক করতে) চাই।

বাগটি পুনরুত্পাদন করা সহজ নয়, তবে এটি ঘটলে তা মারাত্মক।

সম্পূর্ণ স্ট্যাক-ট্রেস:

W/dalvikvm( 7546): threadid=1: thread exiting with uncaught exception (group=0x41987d40)
    E/AndroidRuntime( 7546): FATAL EXCEPTION: main
    E/AndroidRuntime( 7546): Process: com.oblong.mezzedroid, PID: 7546
    E/AndroidRuntime( 7546): java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:3
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3382)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3340)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1810)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1306)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1269)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:523)
    E/AndroidRuntime( 7546):    at org.liboid.recycler_view.RecyclerViewContainer$LiLinearLayoutManager.onLayoutChildren(RecyclerViewContainer.java:179)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1942)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237)
    E/AndroidRuntime( 7546):    at org.liboid.recycler_view.LiRecyclerView.onLayout(LiRecyclerView.java:30)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at com.oblong.mezzedroid.workspace.content.bins.BinsContainerLayout.onLayout(BinsContainerLayout.java:22)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2132)
    E/AndroidRuntime( 7546):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1872)
    E/AndroidRuntime( 7546):    at andro

2
একটি প্রশ্ন: আপনার তিরস্কারটি কতটা সামঞ্জস্যপূর্ণ? আমি জানি এটি এখানে এবং এখানে গুগলের কোডে একটি ত্রুটি । তবে এড়ানো যায়। তো, প্রতিটি ঘোরাঘুরিতে কি এটি ঘটছে?
ভিকভু 13'15

ওহে. এটি খুব কমই ঘটে থাকে, তবে এটি যখন ঘটে তখন এটি অ্যাপের পক্ষে মারাত্মক।
করোলডেপকা

বাগগুলির লিঙ্কগুলির জন্য ধন্যবাদ। প্রথমটি দ্বিতীয়টির চেয়ে বেশি প্রাসঙ্গিক বলে মনে হয়।
করোলডেপকা

1
হ্যাঁ, আমি মনে করি আপনার সেরা বাজিটি কেবল ঘোরার সময় তালিকাগুলিতে পরিবর্তনের অনুমতি না দেওয়া।
ভিকভু

1
আপনি যদি সহজেই পুনরুত্পাদন করতে পারতেন তবে আমি সমস্ত কলকে 'বিজ্ঞপ্তি *' বলার আগে 'getItemCount' এর জন্য মানটি মুদ্রণের পরামর্শ দেব ... আপনি আবিষ্কার করতে পারেন যে আপনার আইটেম গণনাটি আপনার অনুমানের সাথে মেলে না।
রিচ এহমার

উত্তর:


209

আমার একটি (সম্ভবত) সম্পর্কিত সমস্যা ছিল - একটি পুনর্ব্যবহারযোগ্য ভিউয়ের সাথে একটি ক্রিয়াকলাপের একটি নতুন উদাহরণ প্রবেশ করানো, তবে একটি ছোট অ্যাডাপ্টারের সাহায্যে আমার জন্য এই ক্র্যাশটি ট্রিগার করছিল।

RecyclerView.dispatchLayout()কল করার আগে স্ক্র্যাপ থেকে আইটেমগুলি টানতে চেষ্টা করতে পারেন mRecycler.clearOldPositions()। ফলাফলটি হ'ল এটি সাধারণ পুল থেকে আইটেমগুলি টানছিল যা অ্যাডাপ্টারের আকারের চেয়ে বেশি অবস্থানে ছিল।

ভাগ্যক্রমে, এটি কেবল PredictiveAnimationsসক্ষম থাকলে এটিই করে , তাই আমার সমাধানটি সাবক্লাসে ছিল GridLayoutManager( LinearLayoutManagerএকই সমস্যা এবং 'ফিক্স' রয়েছে), এবং supportsPredictiveItemAnimations()মিথ্যা ফিরে আসতে ওভাররাইড করা হয়েছিল:

/**
 * No Predictive Animations GridLayoutManager
 */
private static class NpaGridLayoutManager extends GridLayoutManager {
    /**
     * Disable predictive animations. There is a bug in RecyclerView which causes views that
     * are being reloaded to pull invalid ViewHolders from the internal recycler stack if the
     * adapter size has decreased since the ViewHolder was recycled.
     */
    @Override
    public boolean supportsPredictiveItemAnimations() {
        return false;
    }

    public NpaGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public NpaGridLayoutManager(Context context, int spanCount) {
        super(context, spanCount);
    }

    public NpaGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
        super(context, spanCount, orientation, reverseLayout);
    }
}

4
এটি আমার পক্ষে কাজ করেছে এবং ভবিষ্যদ্বাণীপূর্ণ অ্যানিমেশনগুলি অক্ষম করার ফলে আপনি অ্যানিমেশনগুলি একসাথে হারাতে পারবেন না। সাবাস।
রবার্ট লিবারাতোর

8
আপনাকে অনেক ধন্যবাদ স্যার! লিনিয়ারলআউটম্যানেজারের সাথে তাত্ক্ষণিকভাবে কাজ করেছেন, সম্ভবত আমার দিনগুলি সাশ্রয় করেছেন।
levavare

8
অনেক ধন্যবাদ. এই সমাধানটি লিনিয়ারলআউটআমনেজারের সাথে কাজ করা হয়।
পৃথ্বীরাজ

8
আমি মনে করি এই লোকটি তার প্রাপ্য সহায়তার সম্মানে আমরা একটি মূর্তি তৈরির প্রাপ্য ... এটি ওয়েবে সবচেয়ে খারাপ নথিভুক্ত ইস্যুগুলির মধ্যে একটি, তবে এটি এই সমস্যার মুখোমুখি হয়েছিল বলে মনে হয় ... আমি কী আশ্চর্য হয়েছি আপনি কীভাবে এটি আবিষ্কার করতে পেরেছিলেন? যদি ভবিষ্যদ্বাণীমূলক অ্যানিমেশনগুলি মিথ্যা হয় তবে এড়িয়ে যাবেন, @ কাসহান্ট? কারণ, স্ট্যাকট্রেসটি খুব অস্পষ্ট ...
প্যাড

4
যে কেউ এই হ্যাক ছাড়া এটি ঠিক করতে কিভাবে জানেন? কারণ বিজ্ঞপ্তি ডেটাসেট চেঞ্জডকে ডিফুটিলের পক্ষে বাদ দেওয়া হয়েছিল
অ্যান্টন শুকুরেঙ্কো

83

আমার ক্ষেত্রে (আমার ডেটা স্ট্রাকচারে ডেটা মুছুন / সন্নিবেশ করান) আমার পুনর্ব্যবহারযোগ্য পুলটি সাফ করার দরকার ছিল এবং তারপরে ডেটা সেট পরিবর্তিত হওয়ার বিষয়টি জানান!

mRecyclerView.getRecycledViewPool().clear(); mAdapter.notifyDataSetChanged();


6
আমি সাধারণত এটি বলি না, তবে আপনাকে অনেক ধন্যবাদ। আমি এই ক্র্যাশটিকে সংশোধন করার জন্য সমস্ত চেষ্টা করেছি যা আমি যখন ক্রম অনুসারে তালিকার চারপাশে আইটেমগুলির একটি গোছা সরিয়ে নিই তখন অল্প সময়ে ঘটে যায় sp আমি এই সমস্যাটি সমাধান করার চেষ্টা করার জন্য আক্ষরিক সম্ভবত একটি পুরো সপ্তাহ কাটিয়েছি। আমি আমার মস্তিষ্ককে অন্যরকমভাবে যোগাযোগ করার সুযোগ দেওয়ার চেষ্টা করার জন্য কয়েক মাস এটি থেকে দূরে চলেছি, তারপরে আমার প্রথম গুগলের প্রচেষ্টায় এটি পাওয়া গেছে। তোমার মঙ্গল হোক!
চ্যান্টেল ওসেজো

আমাকে আপনাকে একটি টন কুকি আনতে দেয় যার ফলে আপনি সেগুলির প্রত্যেকটিরই প্রাপ্য। ধন্যবাদ.
antonis_st

আপনি এই কাজ করতে হবে কেন?
ডাবলাক

9
এটি একটি দুর্দান্ত ভারী অপারেশন যা ধরণের পুনর্ব্যবহারযোগ্য দৃষ্টিভঙ্গির উদ্দেশ্যকে পরাস্ত করে।
gjsalot

@gjsalot তাই যদি আমি এটি ব্যবহার করি তবে এটি কিছু সমস্যা তৈরি করতে পারে?
শ্রীকান্ত করুণাঘাট

38

notifyDataSetChanged()পরিবর্তে notifyItem...এই ক্ষেত্রে ব্যবহার করুন ।


5
কিছু ক্ষেত্রে এটি যাওয়ার উপায়। আমার এমন পরিস্থিতি হয়েছিল যেখানে আমি আমার সমস্ত আইটেম প্রতিস্থাপন করেছি, তবে আমি অ্যাডাপ্টারের সাথে সৎ হচ্ছিলাম না, কেবল এটি বলার আগে আমি কিছু নতুন আইটেম (notifyItemRangeInsert) sertedুকিয়েছি, প্রথমে না জানিয়ে আমি আইটেমগুলিও সরিয়ে ফেলেছি। এরপরে অ্যাডাপ্টারটি প্রত্যাশা করেছিল যে সেখানে আরও আইটেম থাকবে আসলে সেখানে ছিল। অ্যাডাপ্টারের কোনও বিজ্ঞপ্তি পদ্ধতি ব্যবহার করে notifyDataSetChanged যেমন notifItemRangeRemoved / সন্নিবেশিত / আপডেট হওয়া প্রত্যাশা করে, কলারের ঠিক কী পরিবর্তন হয়েছিল তা অ্যাডাপ্টারের বলার পুরো দায়িত্ব রয়েছে , অথবা আপনি এই "অসামঞ্জস্য অবস্থার সাথে" শেষ করতে পারেন।
জেএইচ এইচ

19
এটি মোটেই সমাধান নয়।
মিহা_এক্স 64

এটি যাওয়ার উপায় নয়। যদি এটির কাজ করে তবে এর অর্থ হল যে আপনি কেবলমাত্র সীমাটি বিশৃঙ্খলাবদ্ধ করেছেন notifyItem...এবং সংশোধন করেছেন যা সমস্ত আইটেমকে পুনরায় সরবরাহের পরিবর্তে কাজ শুরু করবে start
রঞ্জন

12

আমি mRecycler.setAdapter(itemsAdapter)অ্যাডাপ্টারের সাথে সমস্ত আইটেম যুক্ত করার পরে পর্যন্ত এটি বিলম্ব করে সমাধান করেছি mRecycler.addAll(items)এবং এটি কাজ করে। আমি কেন এটি শুরু করতে পেরেছি তার ধারণা নেই, এটি একটি লাইব্রেরির কোড থেকে আমি দেখেছি এবং "ভুল ক্রমে" এই লাইনগুলি দেখেছি, আমি যথেষ্ট নিশ্চিত এটি যদিও এটি, দয়া করে যদি কেউ এটি নিশ্চিত করতে পারে তবে কেন এটি হয়েছে তাই? এটি এমনকি একটি বৈধ উত্তর কিনা তা নিশ্চিত নয়


আমি মনে করি এটিই সমাধান, আমি একবার অ্যাডাপ্টারে বিলম্ব করলে ঠিক হয়ে যায় আমার বিশ্বাস ... এখন ইউআই থ্রেডে অ্যাডাপ্টার সেট করার সময় এবং এটিতে আইটেম যুক্ত করার পরে এটি পপ আপ হয়।
ইঞ্জিনসেন্স

18
আমি এর swapAdapter(adapter, true)পরিবর্তে ব্যবহার করেছি setAdapter(adapter)এবং এটি সাহায্য করেছে।
ফ্রেঙ্গুলিয়ান

11

আমারও একই সমস্যা ছিল ঠিক কিন্তু একরকম নয়। আমার ক্ষেত্রে 1 পয়েন্টে আমি অ্যারেটি সাফ করে দিচ্ছিলাম যা পুনর্ব্যবহারযোগ্য পর্যবেক্ষণে পাস করা হয়েছিল

mObjects.clear();

এবং notifyDataSetChanged কল না, কারণ আমি চাইনি রিসাইক্লারভিউটি সাথে সাথে মতামতগুলি সাফ করুন। আমি অ্যাসিঙ্কটাস্কে এমওবজেক্টস অ্যারে পুনরায় পূরণ করছিলাম।


9

আমার রিসাইক্লারভিউয়ের সাথে একই সমস্যা ছিল তাই আমি তালিকাটি সাফ হওয়ার পরে ঠিক ডেটা সেট পরিবর্তন সম্পর্কে অ্যাডাপ্টারকে অবহিত করেছি।

mList.clear();
mAdapter.notifyDataSetChanged();

mList.addAll(newData);
mAdapter.notifyDataSetChanged();

1
এই সাধারণ ভুলটি আমাকে এত সময় হারাতে বাধ্য করে, আপনাকে অনেক ধন্যবাদ!
leb1755

7

আমার একই সমস্যা আছে। আমি যখন দ্রুত স্ক্রোল করছিলাম এবং এপিআই কল করছিলাম এবং ডেটা আপডেট করছিলাম তখন ক্রটি হওয়া রোধ করার জন্য সমস্ত কিছু চেষ্টা করার পরে আমি সমাধান পেয়েছি।

mRecyclerView.stopScroll();

এটা কাজ করবে।


এটি একটি সমাধান নয় একটি কাজ। আপনি এটিকে স্ক্রোলটি বন্ধ করতে বাধ্য করছেন। খারাপ ইউএক্স
ডাঃ এএনড্রো

1
@ Dr.aNdRO: অ্যাডাপ্টারের অবস্থান নির্ধারণ করা দরকার এবং যদি আপনি পুনরায় পুনর্বিবেচনা পর্যালোচনা চালিয়ে যান, অ্যাডাপ্টার ডেটা সেট করতে পারে না যা ক্রাশের কারণ। এটি খারাপ ইউএক্স নয়
আনন্দ সাবজনী

1
ধারণা তৈরী কর. ডেটা রিফ্রেশ হওয়ার কারণে স্ক্রোল থামানো খারাপ না।
সুস

6

আমি RecyclerViewব্যাকগ্রাউন্ডে জন্য ডেটা পরিবর্তন করছি ThreadExceptionওপি'র মতোই পেয়েছি । ডেটা পরিবর্তন করার পরে আমি এটি যুক্ত করেছি:

myRecyclerView.post(new Runnable() {
    @Override
    public void run() {
        myRecyclerAdapter.notifyDataSetChanged();
    }
});

আশা করি এটা সাহায্য করবে


ধন্যবাদ মানুষ! এটিই একমাত্র উত্তর যা অ্যান্ড্রয়েড বিকাশের দৃষ্টিকোণ থেকে বোঝা যায়।
ব্যবহারকারী 347187

যদিও আমি এর সাহায্যে সমাধান view.recycler_view.postকরেছি, আমি ব্যবহার করেছি notifyItemInserted। আমার ক্ষেত্রে এটি ইতিমধ্যে ইউআই থ্রেড হয়েছে।
কুলমাইন্ড

6

এই ত্রুটিটি ঘটে যখন অ্যাডাপ্টারে থাকা তালিকাটি পরিষ্কার হয়ে যায় যখন ব্যবহারকারী স্ক্রল করে যা আইটেমধারীর অবস্থান পরিবর্তন করে, তালিকার এবং ইউআই-তে আইটেমের মধ্যে রেফারেন্স হারিয়ে যায়, ত্রুটি পরবর্তী "notifyDataSetChanged" এ ঘটে অনুরোধে ।

ফিক্স:

আপনার আপডেট তালিকা পদ্ধতি পর্যালোচনা করুন। এমন কিছু করলে

mainList.clear();
...
mainList.add() or mainList.addAll()
...
notifyDataSetChanged();

===> Error occur

কিভাবে ঠিক করবো. বাফার প্রসেসিংয়ের জন্য নতুন তালিকার অবজেক্ট তৈরি করুন এবং তার পরে আবার মূল তালিকায় নিযুক্ত করুন

List res = new ArrayList();
…..
res.add();  //add item or modify list
….
mainList = res;
notifyDataSetChanged();

এই দুর্দান্ত সহায়তার জন্য নান কাওকে ধন্যবাদ :)


4

Adapterরেফারেন্সের পরিবর্তে আইটেমি অ্যারেটির অনুলিপিটি ব্যবহার করতে আমার বাস্তবায়নটি সংশোধন করার পরে আমার সমস্যা চলে গেছে । setItems()পদ্ধতি প্রতিটি সময় আমরা দেখানোর জন্য নতুন আইটেম আছে বলা হয়RecyclerView

পরিবর্তে:

private class MyAdapter extends RecyclerView.Adapter<ItemHolder> {
     private List<MyItem> mItems;  

    (....)

    void setItems(List<MyItem> items) {
        mItems = items;
    }
}

আমি করেছিলাম:

void setItems(List<MyItem> items) {
    mItems = new ArrayList<>(items);
}

এটি সমস্যার সমাধান করবে, তবে এটি মূল স্মৃতি থেকে দ্বিগুণ গ্রহণ করবে না?
শ্রীকান্ত করুণাঘাট

@ মিগুয়েলএ.গ্যাব্রিয়েল এটি কি পারফরম্যান্সকে প্রভাবিত করবে? উদাহরণস্বরূপ, আমার ক্ষেত্রে আমি পুনর্বিবেচনার অ্যারে খুব ঘন ঘন আপডেট করছি তাই বর্তমানে আমি এটি করছি suggestionsRecyclerView.swapAdapter(new CandidatesAdapter(mSuggestions), true); এবং এটি আমার public CandidatesAdapter(List<String> suggestionsList) { this.suggestionsList = new ArrayList<>(suggestionsList); }
নির্মাতা

@ মঠিন-চৌদ্দরি সম্ভবত এটি হবে। আপনার নিজের ক্ষেত্রে এটি পরীক্ষা করতে হবে এবং সিদ্ধান্ত নিতে হবে বা প্রস্তাবিত সমাধানগুলির মধ্যে আরও একটি ব্যবহার করার চেষ্টা করতে হবে। যেমনটি আমি বলেছিলাম, এটি কেবলমাত্র এক কর্মক্ষেত্র এবং এটি আমার ক্ষেত্রে আমার পক্ষে কাজ করে।
মিগুয়েল এ। গ্যাব্রিয়েল

3

আমি একই পরিস্থিতির মুখোমুখি হয়েছি। এবং আপনার সংগ্রহ সাফ করার আগে এটি কোড যুক্ত করে সমাধান করা হয়েছিল।

mRecyclerView.getRecycledViewPool().clear();


3

আমার ক্ষেত্রে, আমি আইটেমগুলি আপডেট করছি notifyDataSetChangedএবং একটি অ- UI থ্রেডে কল করছিলাম । বেশিরভাগ সময় এটি কাজ করে, তবে যখন খুব দ্রুত পরিবর্তন ঘটে তখন তা ক্র্যাশ হয়ে যায়। আমি যখন পরিবর্তে, মূলত

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        changeData();
        notifyDataSetChanged();
    }
});

তারপর এটি ক্রাশ বন্ধ।


3

আপনাকে কেবল আপনার তালিকাটি ক্লিয়ার করার দরকার OnPostExecute()নেই এবং করার সময় নয়Pull to Refresh

// Setup refresh listener which triggers new data loading
        swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                AsyncTask<String,Void,String> task = new get_listings();
                task.execute(); // clear listing inside onPostExecute

            }
        });

আমি আবিষ্কার করেছি যে আপনি যখন রিফ্রেশ করার জন্য একটি টানার সময় স্ক্রোল করবেন তখন এটি ঘটেছিল , যেহেতু আমি এর আগে তালিকাটি সাফ করছিলাম async task, ফলে resulting java.lang.IndexOutOfBoundsException: Inconsistency detected.

        swipeContainer.setRefreshing(false);
        //TODO : This is very crucial , You need to clear before populating new items 
        listings.clear();

এইভাবে আপনি কোনও অসঙ্গতি দিয়ে শেষ করবেন না


2

এটি একই সময়ে একাধিক বার অ্যাডাপ্টার সেট করার সাথে সম্পর্কিত হতে পারে। আমার একটি কলব্যাক পদ্ধতি ছিল যা একই সাথে 5-6 বার ট্রিগার হয়েছিল এবং আমি সেই কলব্যাকে অ্যাডাপ্টারটি সেট করেছিলাম যাতে রিসাইক্লডভিউপুল সেই সমস্ত ডেটা সমকালীনভাবে পরিচালনা করতে না পারে। এটি একটি চর্বিযুক্ত সুযোগ তবে আপনি যেকোনভাবে ভাল করে দেখুন।


1
হ্যাঁ একই সমস্যা .. তবে সমাধান? আপনি কেবল কারণটি দিন .. ঠিক করবেন কীভাবে?
রঞ্জিত কুমার

@ রঞ্জিতকুমার, দয়া করে উপরের সমস্যাটি সমাধান করার জন্য আপনার উপায়টি ভাগ করুন। আমি mRecyclerView.getRecycledViewPool ()। ক্লিয়ার () ব্যবহার করে এটি সমাধান করেছি; notifyDataSetChanged আগে ও এডাপ্টরের আপডেট ফাংশন প্রায় সিঙ্ক্রোনাইজ ব্লক ব্যবহার
Attiq রেহমান উর

আপনি কি দয়া করে আমার কোড কটাক্ষপাত করা করতে পারেন আমি মনে করি আমার সমস্যা মত পুলিশের তুমি আমাকে সাহায্য করতে পারেন stackoverflow.com/questions/50213362/...
Mateen চৌধুরী

2

ব্যবহার

notifyDataSetChanged()

পরিবর্তে

notifyItemRangeInserted(0, YourArrayList.size())

এক্ষেত্রে.


1
তবে এটি পারফরম্যান্সের জন্য ঠিক নয়? notifyItemRangeInsert আরও ভাল, সমস্যাটি এখানে পড়ে না
Derekyy

2

এই সমস্যার সমাধানের জন্য রিসাইকাল ভিউ আপডেট করার আগে খালি তালিকার সাথে কেবল notifyDataSetChanged () কল করুন।

উদাহরণ স্বরূপ

//Method for refresh recycle view

    if (!hcpArray.isEmpty())

hcpArray.cियर (); // আপডেট পুনর্ব্যবহারযোগ্য ভিউয়ের তালিকা

adapter.notifyDataSetChanged();

2
কোনও সমাধান নয়।
মিহা_এক্স 64

@ মিলহা ক্র্যাশ সমস্যা সমাধানের জন্য আমি আর কোনও সমাধান পাইনি। তবে উপরের সমাধানটি আমার পক্ষে কাজ করা হয়েছে। যদি এটি সমাধান না হয় তবে আমাকে সঠিক ফিক্সটি বলুন।
EKN

এটা নির্ভর করে. আপনি ডিফুটিল ব্যবহার করতে চেষ্টা করতে পারেন - রিসাইক্লারভিউ সামগ্রীগুলি আপডেট করার জন্য একটি সাধারণ-উদ্দেশ্য সরঞ্জাম tool
মিহা_এক্স 64

2

আমার ক্ষেত্রে আমি সবেমাত্র লাইনটি সরিয়েছি setHasStableIds(true);


তবে হাসস্টেবলআইডস (সত্য) আরভি এর কার্যকারিতা উন্নত করে, এর কোনও বিকল্প সমাধান আছে কি?
শ্রীকান্ত করুণাঘাট

আসলে আমি মনে করি এটি বিভিন্ন কারণে হতে পারে, সুতরাং মূল কারণ কী তার উপর ভিত্তি করে এই সমস্যার বিভিন্ন সমাধান হতে পারে।
শ্রীকান্ত করুণাঘাট

2

আমার ক্ষেত্রে আমি আমার অ্যাডাপ্টারের সামগ্রীগুলি ব্যাকগ্রাউন্ড থ্রেডে পরিবর্তন করার চেষ্টা করছিলাম তবে মূল / ইউআই থ্রেডে নোটিফাই * বলে।

সেটা সম্ভব না! নোটিফিকেশনকে মূল থ্রেডে বাধ্য করার কারণটি হ'ল রিসাইক্লারভিউটি চায় আপনি একই ব্যাক স্ট্যাকে এমনকি মূল থ্রেডে আপনার ব্যাকিং অ্যাডাপ্টারটি সম্পাদনা করতে পারেন।

সমস্যা সমাধানের জন্য নিশ্চিত হয়ে নিন যে আপনার অ্যাডাপ্টারের প্রতিটি অপারেশন পাশাপাশি প্রতিটি বিজ্ঞপ্তি ... কলটি ইউআই / মূল থ্রেডে করা হয়েছে !


2
আপনার অ্যাডাপ্টারের তালিকায় আইটেম যুক্ত করা ব্যাকগ্রাউন্ড থ্রেডে করা উচিত এবং পোস্টস্টেকসুটটিতে কল বিজ্ঞপ্তি দেওয়া উচিত। ইউআই থ্রেডে ডেটা যুক্ত করা অ্যাপ্লিকেশনটিকে কিছু মিলিসেকেন্ড বা সেকেন্ডের জন্য জমা করে তোলে যদি অনেকগুলি ডেটা যোগ করে
ডায়োনি ল্যালোরা

@ ডিওনেলোরের সাথে একমত হয়ে, এটা পরিষ্কার করে দেওয়া উচিত যে "অ্যাডাপ্টারের সামগ্রীতে পরিবর্তন" এর অর্থ নির্দিষ্টভাবে কোনও তথ্য পরিবর্তন করা হয়, আদিম মান, বস্তুর বৈশিষ্ট্য বা বস্তু নিজেই
ওজজি দ্য জায়ান্ট

2

আমি সম্প্রতি নতুন অ্যান্ড্রয়েড আর্কিটেকচার উপাদানগুলির সাথে এই দুষ্টু স্ট্যাক ট্রেসটিতে ছুটে এসেছি। মূলত, আমার ভিউমোডেলে আইটেমগুলির একটি তালিকা রয়েছে যা আমার ফ্রেগমেন্ট দ্বারা পর্যবেক্ষণ করা হয়, লাইভ ডেটা ব্যবহার করে। যখন ভিউমোডেল ডেটার জন্য একটি নতুন মান পোস্ট করে, ফ্রেগমেন্ট অ্যাডাপ্টারের আপডেট করে, এই নতুন ডেটা উপাদানগুলিতে প্রবেশ করে এবং অ্যাডাপ্টারকে জানিয়েছে যে সেখানে পরিবর্তন হয়েছে।

দুর্ভাগ্যক্রমে, অ্যাডাপ্টারে নতুন ডেটা উপাদানগুলিতে যাওয়ার সময়, আমি ভিউমোডেল এবং অ্যাডাপ্টার উভয়ই একই অবজেক্টের রেফারেন্সের দিকে ইঙ্গিত করব এ জন্য অ্যাকাউন্ট করতে ব্যর্থ হয়েছি! মানে আমি যদি ডেটা আপডেট করে এবং কল করিpostValue() হ'ল ভিউমোডেলের মধ্যে থেকে খুব ছোট একটি উইন্ডো রয়েছে যেখানে ডেটা আপডেট করা যেতে পারে এবং অ্যাডাপ্টারটি এখনও অবহিত করা হয়নি!

অ্যাডাপ্টারে প্রবেশের সময় আমার ফিক্সটি ছিল উপাদানগুলির একটি নতুন কপি ইনস্ট্যান্ট করা:

mList = new ArrayList<>(passedList);

এই সুপার ইজি ফিক্সের সাহায্যে আপনি নিশ্চিত করা যেতে পারে যে আপনার অ্যাডাপ্টারটি অবহিত হওয়ার আগে ডান অবধি আপনার অ্যাডাপ্টারের ডেটা পরিবর্তন হবে না।


2

এটি কেবলমাত্র সমাধান যা আমার জন্য কাজ করেছিল এমনকি উপরের সমাধানগুলি থেকে অনেক চেষ্টা করে।

1.) ইনটিলাইজেশন

CustomAdapter scrollStockAdapter = new CustomAdapter(mActivity, new ArrayList<StockListModel>());
list.setAdapter(scrollStockAdapter);
scrollStockAdapter.updateList(stockListModels);

২) অ্যাডাপ্টারে এই পদ্ধতিটি লিখুন

public void updateList(List<StockListModel> list) {
stockListModels.clear();
stockListModels.addAll(list);
notifyDataSetChanged();
}

স্টকলিস্টমোডেলস -> এই তালিকাটি আপনি অ্যাডাপ্টারে ব্যবহার করছেন।


2

আমার জন্য, কোডটির এই লাইনটি যুক্ত করার পরে এটি কাজ করেছিল:

mRecyclerView.setItemAnimator(null);

2
এটি বেশিরভাগ ক্ষেত্রেই ঠিক করা যায় না, আপনি যদি অ্যানিমেশন চান তবে আপনার অ্যাডাপ্টারের কোডটি পুনরায় লিখতে হবে এবং পরিবর্তনগুলি
জানাতে

এটি আমার পক্ষে দুর্দান্ত কাজ করে real আমি সত্যিকারের অ্যাডাপ্টার ব্যবহার করছি যাতে আমি প্রবাহটি নিয়ন্ত্রণ করতে পারি না এবং আমি উইন্ডোঅ্যাক্টিভিটি ট্রান্সশিশনগুলিকে এমন একটি স্টাইলে সক্ষম করেছিলাম যার কারণে এই সমস্যার কারণ মানুষকে আপনি আমার দিনটি বাঁচান thanks
আরুল মণি

1

আপনি যখন আপনার তালিকাটি সাফ করার চেষ্টা করছেন তখন এই সমস্যাটি ঘটতে পারে, আপনি যদি আপনার ডেটা তালিকাটি সাফ করতে যাচ্ছেন বিশেষত যখন আপনি বুলিয়ান পতাকা ব্যবহারের জন্য পুনরায় রিফ্রেশ করার চেষ্টা করছেন, এটি মিথ্যা হিসাবে আরম্ভ করুন এবং অন-রিফ্রেশ পদ্ধতির অভ্যন্তরে এটি সত্য করে তুলুন, আপনার ডেটালিস্টটি সাফ করুন যদি পতাকাটি এটিতে নতুন ডেটা যুক্ত করার আগে সত্য হয় এবং তারপরে এটি মিথ্যা করে।

আপনার কোড এর মত হতে পারে

 private boolean pullToRefreshFlag = false ;
 private ArrayList<your object> dataList ;
 private Adapter adapter ;

 public class myClass extend Fragment implements SwipeRefreshLayout.OnRefreshListener{

 private void requestUpdateList() {

     if (pullToRefresh) {
        dataList.clear
        pullToRefreshFlag = false;
     }

     dataList.addAll(your data);
     adapter.notifyDataSetChanged;


 @Override
 OnRefresh() {
 PullToRefreshFlag = true
 reqUpdateList() ; 
 }

}

1

আমারও আগে একই সমস্যা ছিল। অবশেষে তার জন্য একটি কার্যপ্রণালী খুঁজে পেয়েছি

আমি যা করি তা হ'ল অ্যাডাপ্টারটি সেই আইটেমটি সরিয়েছে এবং তারপরে অ্যাডাপ্টারের ডেটা সেট পরিসীমা পরিবর্তিত হয়েছে তা অবহিত করা

 public void setData(List<Data> dataList) {
      if (this.dataList.size() > 0) {
          notifyItemRangeRemoved(0, dataList.size());
          this.dataList.clear();
      }
      this.dataList.addAll(dataList)
      notifyItemRangeChanged(0, dataList.size());

 }

1

আমি একটি অনুরূপ ইস্যুতে দৌড়ে এসেছি এবং এটি ঠিক বের করে ফেলেছি। আমি পরীক্ষার কেসের জন্য কয়েকটি উদাহরণ কঠোরভাবে কোডড করেছি তবে নিশ্চিত করেছিলাম না যে তারা প্রত্যেকেই একটি অনন্য আইডি দিয়েছে এবং এটি আমার জন্য নীচের ক্র্যাশ ঘটায়। আইডি ফিক্সিংয়ের ফলে সমস্যার সমাধান হয়েছে, আশা করি এটি অন্য কাউকে সহায়তা করে!


1

আমি একবারও ত্রুটি পেয়েছি:

কারণ: আমি একই সাথে পুরানো মুছে ফেলা ভিউহোল্ডারগুলি পাওয়ার চেষ্টা করার সময় একটি অ্যাসিঙ্ক কার্য থেকে একটি পুনর্ব্যবহারযোগ্য ভিউ আপডেট করার চেষ্টা করছিলাম;

কোড: আমি একটি বোতামের প্রেসে ডেটা তৈরি করি, নীচে লজিক

  1. পুনর্ব্যবহারযোগ্য দৃশ্যে শেষ আইটেমগুলি সাফ করুন
  2. ডেটা উত্পন্ন করতে অ্যাসিঙ্ক টাস্ককে কল করুন
  3. OnPostExecute পুনর্ব্যবহারযোগ্য ভিউ আপডেট করুন এবং NotifyDataSetChanged

সমস্যা: আমি যখনই আমার ডেটা তৈরির আগে দ্রুত স্ক্রোল করি

অসঙ্গতি ধরা পড়ে। অবৈধ দর্শন ধারক অ্যাডাপ্টারের অবস্থানভিউহোল্ডার জাভা.এলং.ইনডেক্সআউটআউটফাউন্ডস এক্সেক্সেশন: অসঙ্গতি ধরা পড়ে। অবৈধ আইটেমের অবস্থান 20 (অফসেট: 2)। স্টেট: 3

সমাধান: আমার ডেটা উত্পন্ন করার আগে পুনর্ব্যবহারযোগ্য দৃশ্যটি সাফ করার পরিবর্তে আমি এটিকে রেখে দিই এবং নীচে দেখানো হিসাবে, কল নোটিফাইড্যাটাসেট চেঞ্জড নতুন ডেটা দিয়ে এটি প্রতিস্থাপন করব;

       @Override
        protected void onPostExecute(List<Objects> o) {
            super.onPostExecute(o);
            recyclerViewAdapter.setList(o);
            mProgressBar.setVisibility(View.GONE);
            mRecyclerView.setVisibility(View.VISIBLE);
        }

আপনি কি দয়া করে আমার কোডটি একবার দেখে নিতে পারেন আমার মনে হয় আমার সমস্যাটি আপনার মতো [লিংক] ( স্ট্যাকওভারফ্লো.com
উকশনস /

1

সূচিত করার আগে আপনার লেআউট ম্যানেজারের সমস্ত দর্শন সরান। মত:

myLayoutmanager.removeAllViews();

এটা কাজ করে। স্ক্রোল লোড এবং ট্যাব পরিবর্তন নিয়ে আমার সমস্যা হয়েছিল।
ওয়ারউইকি

1

ListAdapter (androidx.recyclerview.widget.ListAdapter)কল adapter.submitList(null)করার আগে কল ব্যবহার করা adapter.submitList(list):

adapter.submitList(null)
adapter.submitList(someDataList)

0

আমি খুঁজে পেয়েছি যে mRecycler.setLayoutFrozen (সত্য) সেট করা হচ্ছে; সোয়াইপ কনটেনারের অনফ্রেস পদ্ধতিতে।

আমার জন্য সমস্যা সমাধান।

swipeContainer.setOnRefreshListener(new   SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            orderlistRecycler.setLayoutFrozen(true);
            loadData(false);

        }
    });

0

এটি বেশ বাজে বাগ।

আমার আইটেম ক্লিকটি পরিচালনা করতে, আমি এই প্রশ্নেরRecyclerView.OnItemTouchListener মধ্যে থাকা সমাধানের অনুরূপ একটি প্রয়োগ ব্যবহার করেছি ।

RecyclerViewএর ডেটাসোর্সটি রিফ্রেশ করার পরে এবং কোনও আইটেম ক্লিক করার পরে, এটি IndexOutOfBoundsExceptionআমার অ্যাপ্লিকেশনটিকে ক্র্যাশ করবে। যখন কোনও আইটেম ক্লিক করা হয়, RecyclerViewঅভ্যন্তরীণভাবে সঠিক অন্তর্নিহিত ভিউ সন্ধান করে এবং এটিকে আবার অবস্থান দেয়। উত্স কোডটি পরীক্ষা করে দেখলাম যে সেখানে কিছু ছিল TasksএবংThreads নির্ধারিত ছিল। গল্পটি সংক্ষিপ্তভাবে কাটাতে, মূলত এটি কিছু অবৈধ অবস্থা যেখানে দুটি ডাটাসোর্স সংমিশ্রিত হয় এবং সিঙ্ক্রোনাইজ হয় না এবং পুরো জিনিসটি বন্য হয়ে যায়।

এই উপর ভিত্তি করে, আমি আমার বাস্তবায়ন মুছে RecyclerView.OnItemTouchListenerকেবল ক্লিক করুন ধরা ViewHolderএর Adapterআমিঃ

public void onBindViewHolder (final BaseContentView holder, final int position) {

    holder.itemView.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick (View view) {

        // do whatever you like here
      }
    });

}

এটি সেরা সমাধান নাও হতে পারে, তবে আপাতত ক্র্যাশ মুক্ত ..


অনবিন্দকে ডাকা হওয়ার সাথে সাথে প্রতিবার একটি নতুন অবজেক্ট তৈরি করার ফলে প্রচুর পরিমাণে অবজেক্ট সংগ্রহ করা হবে যা আবর্জনা সংগ্রহ করা হতে পারে এবং ব্যবহারকারীর তুষারপাতের অভিজ্ঞতা হতে পারে।
ডিফাইনরা

0

লিন্ট আমাকে অসঙ্গতি সম্পর্কে পরামর্শ দিয়েছিল: আমি লিখেছি (অনবিন্দভিউোল্ডার ()):

pholder.mRlayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        doStuff(position);
                    }
                });

যার দ্বারা প্রতিস্থাপন করতে হয়েছিল:

pholder.mRlayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        doStuff(pholder.getAdapterPosition());
                    }
                });

আপনার কোডে দুটি কোড চালান এবং তারপরে সম্পূর্ণ ব্যাখ্যার জন্য লিন্ট চালান !!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.