5

Here is the deal, I have a RecycleView Adapter which inflates layout on onCreateViewHolder. When I try to do the following actions in order this happens:

  1. Application created without any problem
  2. Went into multitasking window
  3. Came back to app
  4. InflateException

Error is occurring at Fresco's SimpleDraweeView which is defined in xml.

<com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/photo"
        android:layout_width="match_parent"
        android:layout_height="@dimen/image_nobar"
        android:layout_alignParentEnd="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:adjustViewBounds="true"
        android:contentDescription="@string/photo"
        fresco:placeholderImage="@drawable/fry"
        fresco:actualImageScaleType="focusCrop" />

This is how I'm setting the adapter to RecycleView

list = new ArrayList<>();
gagInfo gi = new gagInfo();
list.add(gi.setEmpty());
recList.setAdapter(new gagAdapter(list, context));
populateRecyclerView(recList);
private void populateRecyclerView(final RecyclerView rView) {

    new Thread(new Runnable() {
        @Override
        public void run() {
            SharedPreferences prefs = getSharedPreferences(GAGS, MODE_PRIVATE);

            Map<String, ?> allEntries = prefs.getAll();
            list = new ArrayList<>();
            JSONObject obj;
            String keyObject;
            Boolean first = true;
            for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
                String entryValue = entry.getValue().toString();
                keyObject = entry.getKey();

                try {
                    JSONObject entryObject = new JSONObject(entryValue);
                    obj = entryObject.getJSONObject("nameValuePairs");
                    gagInfo gi = new gagInfo();
                    Log.d("JSON", "Processing... " + keyObject);

                    try {
                        gi.title = obj.getString("title");
                        gi.likes = obj.getString("likes");
                        gi.comments = obj.getString("comments");
                        gi.saved_date = obj.getString("saved_date");
                        gi.file_path = obj.getString("file_path");
                        gi.photoId = obj.getString("photoId");

                        list.add(gi);

                        if (first) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    ca = new gagAdapter(list, context);
                                    rView.setAdapter(ca);
                                }
                            });
                            first = false;
                        } else {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    ca.notifyItemInserted(list.size() - 1);
                                }
                            });
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                        SharedPreferences.Editor editor = prefs.edit();
                        editor.remove(keyObject);
                        editor.apply();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            Collections.sort(list);
        }
    }).start();
}

I have tried to override onResume in the Activity where I set Adapter to RecycleView (Main reason: Resume from onCreate to avoid passing null Adapter):

@Override
    protected void onResume() {
        String action = getIntent().getAction();
        if (action == null || !action.equals("Created")) {
            Log.v("HCA", "Restart");
            Intent intent = new Intent(this, HomeCardActivity.class);
            startActivity(intent);
            finish();
        } else {
            getIntent().setAction(null);
        }
        super.onResume();
    }

And this is how I inflate layout in my adapter. I also tried to retry to inflate layout if it fails.

@Override
    public gagViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(viewGroup.getContext());
        String card = prefs.getString("card_view", "0");
        Integer layoutID;

        if (card.equals("0")) {
            layoutID = R.layout.card_layout;
        } else {
            layoutID = R.layout.card_layout_nowhitebar;
        }

        View itemView;
        int count = 0;
        int maxTries = 5;

        do try { //TODO: Why LayoutInflater fails after third try?
            itemView = LayoutInflater.
                    from(viewGroup.getContext()).
                    inflate(layoutID, viewGroup, false);
            if (!(itemView == null)) break;
        } catch (InflateException ie) {
            Log.e("LayoutInflater", ie.toString());
            if (++count == maxTries) throw ie;
        } while (true);

        return new gagViewHolder(itemView);
    }

Logcat

android.view.InflateException: Binary XML file line #15: Binary XML file line #15: Error inflating class <unknown>
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
                                                                  at com.denizugur.ninegagsaver.gagAdapter.onCreateViewHolder(gagAdapter.java:134)
                                                                  at com.denizugur.ninegagsaver.gagAdapter.onCreateViewHolder(gagAdapter.java:25)
                                                                  at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5779)
                                                                  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5003)
                                                                  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4913)
                                                                  at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029)
                                                                  at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414)
                                                                  at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377)
                                                                  at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)
                                                                  at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260)
                                                                  at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3069)
                                                                  at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3518)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1080)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
                                                                  at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:435)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
                                                                  at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
                                                                  at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                                                  at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
                                                                  at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
                                                                  at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:3193)
                                                                  at android.view.View.layout(View.java:17938)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                  at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2666)
                                                                  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2367)
                                                                  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1437)
                                                                  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7397)
                                                                  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
                                                                  at android.view.Choreographer.doCallbacks(Choreographer.java:695)
                                                                  at android.view.Choreographer.doFrame(Choreographer.java:631)
                                                                  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
                                                                  at android.os.Handler.handleCallback(Handler.java:739)
                                                                  at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                  at android.os.Looper.loop(Looper.java:158)
                                                                  at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
                                                               Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class <unknown>
                                                                at android.view.LayoutInflater.createView(LayoutInfla
Deniz da King
  • 381
  • 1
  • 4
  • 12
  • Please edit to show how you know the error is occurring in that class. In other words, the logcat, please – OneCricketeer Jul 28 '16 at 14:13
  • Note that, logcat says for class but it's SimpleDraweeView – Deniz da King Jul 28 '16 at 15:45
  • Looks like you cut off the logcat, the `Caused by` reason is important – OneCricketeer Jul 28 '16 at 15:46
  • I think ACRA cuts it off. I'll try without ACRA – Deniz da King Jul 28 '16 at 15:47
  • It didn't change anything. I think it's same as start of the logcat – Deniz da King Jul 28 '16 at 15:49
  • Okay, then show the XML and mention what's at line 15 – OneCricketeer Jul 28 '16 at 15:51
  • Not really sure what to tell you if you are able to load other instances of that same view – OneCricketeer Jul 28 '16 at 15:59
  • 1
    Well here is the good and bad news: If I remove Line #15 everything works as expected. Bad news I need the view – Deniz da King Jul 28 '16 at 16:04
  • Are you able to make a [mcve] of the problem? – OneCricketeer Jul 28 '16 at 16:13
  • I guess. I removed every reference to SimpleDraweeView in gagAdapter and everything worked. Then enabled them again and problem is here all again. – Deniz da King Jul 28 '16 at 16:16
  • Did you set up Fresco correctly? This includes adding the Gradle dependency, initializing Fresco and configuring ProGuard accordingly in case you've enabled it. What's line 15 exactly? ` – Alexander Oprisnik Jul 31 '16 at 00:37
  • I believe Fresco is working fine in some cases as it loads perfectly for the first time. Maybe when app goes to `onPause` cache deletes itself and it causes the problem. @AlexanderOprisnik – Deniz da King Jul 31 '16 at 07:52
  • So you're saying that it works most of the time and you only see the crash sometimes? That's an important info. How big are your images? Do you use animations? Your app could run out of memory. There is a similar question where the same happened: https://stackoverflow.com/questions/20680451/inflateexception-binary-xml-file-line-1-error-inflating-class-unknown-cause – Alexander Oprisnik Jul 31 '16 at 09:37
  • @AlexanderOprisnik Images are small in file size and loaded to SDV with `focusCrop` option. I use slide animation with `CardView`'s and SDV's are inside the `CardView` but that animation controller is after `onCreateViewHolder` and DraweeController assignment. – Deniz da King Jul 31 '16 at 10:48
  • Do you think that animation is interfering with fresco's caching? – Deniz da King Jul 31 '16 at 10:52
  • So you don't have animated GIFs / WebPs? Animated images are usually memory-heavy, and can lead too OOMs if not used carefully. Please also answer my other previous questions, especially the first one. I'm pretty sure that `CardView` animations should just work. What images and how many (file type, size, dimensions)? How frequently does the error occur(e.g. when you scroll a long list of images etc.)? Does it always reproduce? You should also take a look at your app's memory usage to confirm that it's a memory issue. – Alexander Oprisnik Jul 31 '16 at 11:07
  • No, no animated images. Crash happens if I go to multitasking window or any other app then come back to app (second or third attempt). Images are not more than 500kb on storage (mostly png or jpeg, Some images are 10k px long but they are downsampled and saved before showing them). Should we move this to chat? – Deniz da King Jul 31 '16 at 11:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118747/discussion-between-alexander-oprisnik-and-deniz-da-king). – Alexander Oprisnik Jul 31 '16 at 14:02

1 Answers1

2

Pass context through Adapter constructor from Activity (this) or (getActivity()). Seems like viewGroup context is null when reload.