3

I am making a simple app which has a recyclerview with staggered Layout loading the data from server with the help of PHP scripts using the Volley Library When I Click on the Item in the RecyclerView my App craches with the below error log.

Also when I look at the Memory logs the app is using lots of memory in just loading the data from server into recyclerView

Log //On App start

I/Choreographer: Skipped 189 frames!  The application may be doing too much work on its main thread.
I/art: Background partial concurrent mark sweep GC freed 3797(174KB) AllocSpace objects, 1(36KB) LOS objects, 6% free, 56MB/60MB, paused 19.976ms total 90.718ms

Error Log //after clicking the item in the RecyclerView

I/art: Alloc sticky concurrent mark sweep GC freed 10628(425KB) AllocSpace objects, 5(562KB) LOS objects, 2% free, 59MB/60MB, paused 476us total 7.071ms
I/art: Alloc partial concurrent mark sweep GC freed 928(67KB) AllocSpace objects, 1(16KB) LOS objects, 6% free, 58MB/62MB, paused 647us total 37.510ms
I/art: Alloc concurrent mark sweep GC freed 241(23KB) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 574us total 49.041ms
I/art: Forcing collection of SoftReferences for 21MB allocation
I/art: Alloc concurrent mark sweep GC freed 13(472B) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 429us total 16.959ms
E/art: Throwing OutOfMemoryError "Failed to allocate a 22400012 byte allocation with 4194304 free bytes and 5MB until OOM"I/art: Alloc sticky concurrent mark sweep GC freed 5(608B) AllocSpace objects, 0(0B) LOS objects, 3% free, 58MB/60MB, paused 509us total 8.143ms
I/art: Alloc partial concurrent mark sweep GC freed 17(480B) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 5.517ms total 17.409ms
I/art: Alloc concurrent mark sweep GC freed 14(448B) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 1.077ms total 107.298ms
I/art: Forcing collection of SoftReferences for 21MB allocation
I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 620us total 36.488ms
E/art: Throwing OutOfMemoryError "Failed to allocate a 22400012 byte allocation with 4194304 free bytes and 5MB until OOM"
D/skia: --- allocation failed for scaled bitmap
D/AndroidRuntime: Shutting down VM
FATAL EXCEPTION: main
Process: com.trueblueoperator.swachhapp, PID: 25499
  java.lang.OutOfMemoryError: Failed to allocate a 22400012 byte allocation with 4194304 free bytes and 5MB until OOM
  at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:988)
  at android.content.res.Resources.loadDrawableForCookie(Resources.java:2474)
  at android.content.res.Resources.loadDrawable(Resources.java:2381)
  at android.content.res.TypedArray.getDrawable(TypedArray.java:749)
  at android.widget.ImageView.<init>(ImageView.java:146)
  at android.widget.ImageView.<init>(ImageView.java:135)
  at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:58)
  at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:54)
  at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:95)
  at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:938)
  at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:992)
  at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:725)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
  at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
  at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
  at com.trueblueoperator.swachhapp.StoryDetailFragment.onCreate(StoryDetailFragment.java:45)
  at android.app.Activity.performCreate(Activity.java:5990)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
  at android.app.ActivityThread.access$800(ActivityThread.java:151)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:135)
  at android.app.ActivityThread.main(ActivityThread.java:5254)
  at java.lang.reflect.Method.invoke(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Here is my Code for Fragment class containing the Recycler View

FragmetnAllStory.java file

public class FragmentAllStory extends Fragment implements SwipeRefreshLayout.OnRefreshListener{// implements RecyclerView.OnScrollChangeListener {

//Creating a List of superheroes
private List<AllStoryData> allStoryDataList;

//Volley Request Queue
private RequestQueue requestQueue;

private ProgressBar progressBar;
//The request counter to send ?page=1, ?page=2  requests
private int requestCount = 1;
private RecyclerView recyclerView;
private SwipeRefreshLayout swipeRefreshLayout;
private RecyclerView.Adapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    requestCount = 1;
    View v = inflater.inflate(R.layout.fragment_all_story, container, false);
    progressBar = (ProgressBar) v.findViewById(R.id.progress_bar);

    swipeRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipeRefreshLayout);
    swipeRefreshLayout.setOnRefreshListener(this);
    recyclerView = (RecyclerView) v.findViewById(R.id.recycler_view2);//new RecyclerView(getActivity());
    if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, 1));
    }
    else {
        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, 1));
    }
    allStoryDataList = new ArrayList<>();
    requestQueue = Volley.newRequestQueue(getContext());
    //getData();
    recyclerView.addOnScrollListener(new OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            if(isLastItemDisplaying(recyclerView))
            {
                getData();
            }

        }
    });
    adapter = new AllStoryAdapter(allStoryDataList, getActivity());
    recyclerView.setAdapter(adapter);


    return v;
}

//Request to get json from server we are passing an integer here
//This integer will used to specify the page number for the request ?page = requestcount
//This method would return a JsonArrayRequest that will be added to the request queue
    private JsonArrayRequest getDataFromServer(int requestCount) {

    //Displaying Progressbar
    progressBar.setVisibility(View.VISIBLE);


    //JsonArrayRequest of volley
    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Config.DATA_URL + String.valueOf(requestCount),
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    //Calling method parseData to parse the json response
                    parseData(response);
                    //Hiding the progressbar
                    progressBar.setVisibility(View.GONE);
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    progressBar.setVisibility(View.GONE);
                    //If an error occurs that means end of the list has reached
                    Toast.makeText(getContext(), "No More Items Available", Toast.LENGTH_SHORT).show();
                }
            });

    //Returning the request
    return jsonArrayRequest;
}

@Override
public void onResume() {
    super.onResume();
    requestCount =1;
    allStoryDataList.clear();
    getData();
}

//This method will get data from the web api
private void getData() {
    //Adding the method to the queue by calling the method getDataFromServer
    requestQueue.add(getDataFromServer(requestCount));
    //Incrementing the request counter
    requestCount++;
    swipeRefreshLayout.setRefreshing(false);
}

//This method will parse json data
private void parseData(JSONArray array) {
    for (int i = 0; i < array.length(); i++) {
        //Creating the superhero object
        AllStoryData allStoryData = new AllStoryData();
        JSONObject json = null;
        try {
            //Getting json
            json = array.getJSONObject(i);

            //Adding data to the superhero object
            allStoryData.setImageUrl(json.getString(Config.TAG_IMAGE_URL));
            allStoryData.setName(json.getString(Config.TAG_NAME));
            allStoryData.setPublisher(json.getString(Config.TAG_PUBLISHER));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        //Adding the superhero object to the list
        allStoryDataList.add(allStoryData);
        Log.d("ListSuper", "" + allStoryDataList);
    }

    //Notifying the adapter that data has been added or changed
    adapter.notifyDataSetChanged();
}

//This method would check that the recyclerview scroll has reached the bottom or not
private boolean isLastItemDisplaying(RecyclerView recyclerView) {
    int[] info = new int[3];
    if (recyclerView.getAdapter().getItemCount() != 0) {
        ((StaggeredGridLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPositions(info);
        Log.d("info", "" + info[0] + " " + info[1]);
        if (info[0] == recyclerView.getAdapter().getItemCount() - 1 || info[1] == recyclerView.getAdapter().getItemCount() - 1 || info[2] == recyclerView.getAdapter().getItemCount() - 1)
            return true;
    }
    return false;
}

@Override
public void onRefresh() {
 requestCount =1;
    allStoryDataList.clear();
    getData();
}
}

StoryDetailFragment.java file

public class StoryDetailFragment extends AppCompatActivity implements View.OnClickListener, AppBarLayout.OnOffsetChangedListener {

TextView textView;
TextView like;
ImageView imageView;
String requestString;
RequestParams params = new RequestParams();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_story_detail); // error line 45

    // Intent Message sent from Broadcast Receiver
    requestString = getIntent().getStringExtra("Heading");

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);

    imageView = (ImageView) findViewById(R.id.story_image);
    like = (TextView) findViewById(R.id.likes);
    if (requestString != null) {
        textView = (TextView) findViewById(R.id.story_detail_message);
        textView.setText(requestString);
    }

    AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.app_bar);
    appBarLayout.addOnOffsetChangedListener(this);
    FloatingActionButton fab1 = (FloatingActionButton) findViewById(R.id.fab1);
    FloatingActionButton fab2 = (FloatingActionButton) findViewById(R.id.fab2);
    fab1.setOnClickListener(this);
    fab2.setOnClickListener(this);

    getData();


}


private void getData() {

    params.put("heading", "" + requestString);
    // Make RESTful webservice call using AsyncHttpClient object
    AsyncHttpClient client = new AsyncHttpClient();

    client.get(Config.DETAIL_URL, params,
            new JsonHttpResponseHandler() {

                // When the response returned by REST has Http
                // response code '200'

                @Override
                public void onSuccess(JSONArray response) {

                    Log.d("result",""+response);
                    try {
                        JSONObject result = response.getJSONObject(0);
                        textView.setText((CharSequence) result.get("detailstory"));
                        like.setText((CharSequence) result.get("likes"));
                        String res = (String) result.get("images");
                        //URL url = new URL(res);
                        //Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
                        new DownloadImagesTask().execute(res);


                        Log.d("result",""+res);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    //super.onSuccess(response);
                }


                // When the response returned by REST has Http
                // response code other than '200' such as '404',
                // '500' or '403' etc


                @Override
                public void onFailure(int statusCode, Throwable error, JSONArray errorResponse) {
                    // When Http response code is '404'
                    if (statusCode == 404) {
                        Toast.makeText(StoryDetailFragment.this,
                                "Requested resource not found",
                                Toast.LENGTH_LONG).show();
                    }
                    // When Http response code is '500'
                    else if (statusCode == 500) {
                        Toast.makeText(StoryDetailFragment.this,
                                "Something went wrong at server end",
                                Toast.LENGTH_LONG).show();
                    }
                    // When Http response code other than 404, 500
                    else {
                        Toast.makeText(
                                StoryDetailFragment.this,
                                "Unexpected Error occcured! [Most common Error: Device might "
                                        + "not be connected to Internet or remote server is not up and running], check for other errors as well",
                                Toast.LENGTH_LONG).show();
                    }
                }

            });
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    finish();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == android.R.id.home) {
        onBackPressed();
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.fab1:
            // Code for button like click

            break;

        case R.id.fab2:
            // Code for saving the articles


            break;
    }
}

@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
    if (Math.abs(verticalOffset) <= appBarLayout.getTotalScrollRange() - 120) {
        like.setVisibility(TextView.VISIBLE);
    } else {
        like.setVisibility(TextView.GONE);
    }
}

public class DownloadImagesTask extends AsyncTask<String, Void, Bitmap> {

    @Override
    protected Bitmap doInBackground(String... params) {
        return download_Image(params[0]);
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        imageView.setImageBitmap(result);
    }

    private Bitmap download_Image(String url) {

        Bitmap bmp = null;
        try {
            URL ulrn = new URL(url);
            HttpURLConnection con = (HttpURLConnection) ulrn.openConnection();
            InputStream is = con.getInputStream();
            bmp = BitmapFactory.decodeStream(is);
            if (null != bmp)
                return bmp;

        } catch (Exception e) {
        }
        return bmp;
    }
}
}

XML File fragment_story_detail.xml

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.trueblueoperator.samplescrolling.ScrollingActivity">

<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:fitsSystemWindows="true"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            android:id="@+id/story_image"
            android:layout_width="match_parent"
            android:layout_height="192dp"
            android:scaleType="centerCrop"
            android:src="@drawable/image"
            app:layout_collapseMode="parallax" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_scrolling"/>

<TextView
    android:id="@+id/likes"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingLeft="5dp"
    android:paddingBottom="5dp"
    android:paddingTop="5dp"
    android:paddingRight="70dp"
    android:layout_marginRight="10dp"
    android:textSize="20dp"
    android:background="@drawable/rounded_corner"
    android:text="100"
    app:layout_anchor="@id/app_bar"
    app:layout_anchorGravity="right|bottom"
    />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/like"
    app:layout_anchor="@id/app_bar"
    app:layout_anchorGravity="right|bottom" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/like"
    android:layout_gravity="bottom|right" />

</android.support.design.widget.CoordinatorLayout>
Yogesh Yadav
  • 133
  • 3
  • 11

3 Answers3

4

Whats your logcat throws

E/art: Throwing OutOfMemoryError "Failed to allocate a 22400012 byte allocation with 4194304 free bytes and 5MB until OOM"I/art: Alloc 14(448B) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 1.077ms total 107.298ms I/art: Forcing collection of SoftReferences for 21MB allocation I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 6% free, 58MB/62MB, paused 620us total 36.488ms E/art: Throwing OutOfMemoryError "Failed to allocate a 22400012 byte allocation with 4194304 free bytes and 5MB until OOM" D/skia: --- allocation failed for scaled bitmap

Java heap space error will be triggered when the application attempts to add more data into the heap space area, but there is not enough room for it.

Please reduce Image Sizes & Increase Your VM Heap Size (AVD) .

Each Android-powered device has a different amount of RAM available to the system and thus provides a different heap limit for each app. You can call getMemoryClass() to get an estimate of your app's available heap in megabytes. If your app tries to allocate more memory than is available here, it will receive an OutOfMemoryError.

Advice

It's not a good idea to use android:largeHeap="true" .

Please read about

  1. Managing Your App's Memory

  2. Strange out of memory issue while loading an image to a Bitmap object

IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
1

Resize your image bitmap.

int height = (bitmap.getHeight() * 512 / bitmap.getWidth());
Bitmap scale = Bitmap.createScaledBitmap(bitmap, 512,height, true);
imageView.setImageBitmap(scale);
  • In bitmap use your own bitmap which you download and convert to bitmap.
Chirag Savsani
  • 6,020
  • 4
  • 38
  • 74
0

To avoid this problem, you can add android:largeHeap="true" in <application/> tag of manifest.xml file.