Reputation: 55
My application crashes when I try to navigate to other activities. I believe it's due to the number of pictures I have in my drawables and setting on my application. I have a ListView and an ArrayAdapter set up so I'm not sure why it's using so much memory. Any ideas?
10-29 20:56:52.287 18391-18391/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.android.tourguide, PID: 18391 java.lang.OutOfMemoryError: Failed to allocate a 366378124 byte allocation with 16777216 free bytes and 24MB until OOM
Here's my code:
Main Activity
package com.example.android.tourguide;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
CategoryAdapter adapter = new CategoryAdapter(this, getSupportFragmentManager());
viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
}
Fragment
package com.example.android.tourguide;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.RatingBar;
import java.util.ArrayList;
/**
* A simple {@link Fragment} subclass.
*/
public class RestaurantsFragment extends Fragment {
public RestaurantsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.word_list, container, false);
final ArrayList<Information> words = new ArrayList<Information>();
words.add(new Information(R.drawable.restaurant_1, "Rashid's House", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_2, "Moo Moo Cow", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_3, "Burger 7", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_4, "Mini Horse", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_5, "Prime Prime!", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_6, "Halal Cart 96", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_7, "Half Moon", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_8, "Mourice's Steakhouse", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_9, "The Rudeboy", "Description", R.drawable.five_star_rating));
words.add(new Information(R.drawable.restaurant_10, "Meowth's Lair", "Description", R.drawable.five_star_rating));
InformationAdapter itemsAdapter = new InformationAdapter(getActivity(), words);
ListView listView = (ListView) rootView.findViewById(R.id.list);
listView.setAdapter(itemsAdapter);
return rootView;
}
}
InformationActivity
package com.example.android.tourguide;
import static android.R.attr.description;
import static com.example.android.tourguide.R.id.place;
/**
* Created by msanli on 10/27/2016.
*/
public class Information {
private int mImageResourceId;
private String mPlace;
private String mDescription;
private int mRatingBarResourceId;
public Information(int imageResourceId, String place, String description, int ratingBarResourceId ){
mImageResourceId = imageResourceId;
mPlace = place;
mDescription = description;
mRatingBarResourceId = ratingBarResourceId;
}
public int getImageResourceId() {
return mImageResourceId;
}
public String getPlace(){
return mPlace;
}
public String getDescription(){
return mDescription;
}
public int getRatingBarResourceId(){
return mRatingBarResourceId;
}
}
InformationAdapter
package com.example.android.tourguide;
import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by msanli on 10/27/2016.
*/
public class InformationAdapter extends ArrayAdapter<Information> {
public InformationAdapter(Activity context, ArrayList<Information> words){
super(context, 0, words);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
// Get the {@link Word} object located at this position in the list
Information currentInformation = getItem(position);
ImageView imageImageView = (ImageView) listItemView.findViewById(R.id.image_place);
imageImageView.setImageResource(currentInformation.getImageResourceId());
// Find the TextView in the list_item.xml layout with the ID version_name
TextView nameTextView = (TextView) listItemView.findViewById(R.id.place);
// Get the version name from the current Word object and
// set this text on the name TextView
nameTextView.setText(currentInformation.getPlace());
// Find the TextView in the list_item.xml layout with the ID version_number
TextView descriptionTextView = (TextView) listItemView.findViewById(R.id.description);
// Get the version number from the current Word object and
// set this text on the name TextView
descriptionTextView.setText(currentInformation.getDescription());
ImageView ratingBarImageView = (ImageView) listItemView.findViewById(R.id.ratings_bar);
ratingBarImageView.setImageResource(currentInformation.getRatingBarResourceId());
View textContainer = listItemView.findViewById(R.id.text_container);
return listItemView;
}
}
CategoryAdapter
package com.example.android.tourguide;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
/**
* Created by msanli on 10/29/2016.
*/
public class CategoryAdapter extends FragmentPagerAdapter {
private Context mContext;
public CategoryAdapter(Context context, FragmentManager fm){
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position) {
if (position == 0) {
return new RestaurantsFragment();
} else if (position == 1) {
return new ParksFragment();
} else if (position == 2) {
return new EntertainmentFragment();
} else {
return new AttractionsFragment();
}
}
@Override
public int getCount() {
return 4;
}
@Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return mContext.getString(R.string.category_restaurants);
}else if (position == 1){
return mContext.getString(R.string.category_parks);
}else if (position == 2){
return mContext.getString(R.string.category_entertainment);
}else{
return mContext.getString(R.string.category_attractions);
}
}
}
Upvotes: 0
Views: 327
Reputation: 3241
The problem you face is the result of two things:
Android works with images in uncompressed form. An image allocates byte-array that is basically proportional to the number of pixels in it. For example if you have 800x640 image you get 0.5 MB byte-array in memory.
Your drawable-dpi folder does not match the screen dpi, thus the image is scaled to match the screen dpi, increasing the size of the allocated byte-array by multiple times.
Assume you store your 800x640 image in drawable
(or drawable-mdpi
) which corresponds to 160dpi (i.e. physical image dimensions are 5 x 4 inches):
As Shuvro wrote you can avoid scaling by putting your images to drawable-nodpi
folder. The downside is that you will waste memory for the devices with lower resolution, since the corresponding physical dimensions will be bigger than needed.
IIUC you have a list of thumbnails and you use full images from drawable
to populate it. The proper solution would be to use thumbnail versions of your images in corresponding dpi folders. That will minimize amount of allocated memory and increase the performance by avoiding scaling.
See more: https://developer.android.com/guide/practices/screens_support.html
Upvotes: 0
Reputation: 4023
Try this, where you drawable folder is located (app->src->main->main->res
) , create a folder named it drawable-nodpi
, put your all the images there .
Let me know if it works for you
Upvotes: 1