2016-10-30 3 views
0

Мое приложение падает, когда я пытаюсь перейти к другим действиям. Я считаю, что это связано с количеством фотографий, которые у меня есть в моих ресурсах и настройке в моем приложении. У меня есть ListView и ArrayAdapter, поэтому я не уверен, почему он использует так много памяти. Есть идеи?Ошибка памяти - Оптимизация?

10-29 20: 56: 52.287 18391-18391 /? E/AndroidRuntime: FATAL ИСКЛЮЧЕНИЕ: главный процесса: com.example.android.tourguide, PID: 18391 java.lang.OutOfMemoryError: Не удалось не выделить распределение 366378124 байт с 16777216 свободных байтов и 24MB до ООМ

Вот мой код:

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); 
} 

} 

Фрагмент

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); 
    } 

} 
} 
+0

Это слишком много памяти используется. У вас где-то есть утечка памяти, вам придется пройти и отладить. Отправьте некоторый код частей, о которых идет речь. – TheValyreanGroup

+0

add android: LargeHeap = true в теге активности манифеста. –

+0

поделитесь своим кодом –

ответ

1

Попробуйте, где рисуем папка находится (app->src->main->main->res), создайте папку с именем его drawable-nodpi, положить туда все ваши изображения. Дайте мне знать, если он работает для вас

+0

Hi Shuvro, Мне удалось создать различные папки с возможностью переноса плотности и поместить туда все мои изображения. Теперь это работает. Тем не менее, я вижу прыжок в памяти при переходе от первого фрагмента ко второму (не уверен, находится ли он в нормальном диапазоне) с 6.60 мб до 17.21 мб! После перехода к третьему фрагменту он перескакивает до 41 Мб! Это нормально? – Mir

+0

Вы создали папку drawable-nodpi, как я уже упоминал, и разместил там все изображения? –

+0

Да, но у меня также есть изображения в других папках с возможностью переноса плотности. Должен ли я удалять старые доступные папки? – Mir

0

Проблема вы сталкиваетесь, является результатом двух вещей:

  1. Android работает с изображениями в несжатом виде. Изображение выделяет байтовый массив, который в основном пропорционален количеству пикселей в нем. Например, если у вас есть изображение 800x640, вы получаете 0,5 Мбайт байтового массива в памяти.

  2. Ваша папка с рисунком-dpi не соответствует экрану dpi, поэтому изображение масштабируется в соответствии с разрешением экрана, увеличивая размер выделенного байтового массива на несколько раз.

Предположим, что вы храните 800x640 изображение в drawable (или drawable-mdpi), что соответствует 160dpi (т.е. физические размеры изображения составляют 5 х 4 дюйма):

  • Расширение будет происходить на устройстве с 320dpi разрешение экрана: поскольку экран имеет в два раза больше пикселей на дюйм, чем изображение, у вас будет 1600x1280 пикселей, выделенных для изображения в памяти (сохраняя размеры физического изображения 5 x 4 дюйма).
  • Уменьшение масштаба произойдет на устройстве с разрешением экрана 120 точек на дюйм: поскольку экран имеет на 1/4 пикселя на дюйм, чем изображение, у вас будет 600x480 пикселей, выделенных для изображения в памяти (сохранение физических размеров изображения 5 x 4 дюймов).

Как пишет Shuvro, вы можете избежать масштабирования, разместив свои изображения в папке drawable-nodpi. Недостатком является то, что вы потеряете память для устройств с более низким разрешением, так как соответствующие физические размеры будут больше, чем необходимо.

IIUC у вас есть список миниатюр, и вы используете полные изображения от drawable, чтобы заполнить его. Правильным решением будет использование миниатюрных версий ваших изображений в соответствующих папках с тэгами. Это позволит свести к минимуму количество выделенной памяти и повысить производительность, избегая масштабирования.

Смотреть еще: https://developer.android.com/guide/practices/screens_support.html

Смежные вопросы