Reputation: 1154
From what I've seen here it is possible to half the memory usage, but that doesn't seem enough. My case, like the one referenced, involves loading drawables into ImageViews. Each drawable is smaller than 20kb, but uses ~15mb of memory to load. Why is so much memory used? How can I reduce memory consumption by more than half? Or, should I place the dialog in its own activity rather than a fragment?
DialogFragment Class
public class CollectableDialogFragment extends DialogFragment {
public static final String LOG_TAG = CollectableDialogFragment.class.getSimpleName();
/*Constants for setting Bundle keys that will be passed to this fragment*/
public static final String SQLITE_DATA = "sqliteData";
public static final String FIREBASE_DATA = VideoGame.KEY_UNIQUE_NODE_ID;
private Context context;
/*Object containing video game's data*/
private VideoGame videoGame;
/*Instantiated views*/
private View view;
private ImageView usaFlag;
private ImageView japanFlag;
private ImageView euFlag;
private ImageView game;
private ImageView manual;
private ImageView box;
private CustomEditText noteEditText;
/*Initialize contentProviderBundle and componentsOwned, and handle clicking*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(LOG_TAG, "Entered DialogFragment!");
if (getArguments() != null) {
/*Handles adding new item to collection*/
if (getArguments().containsKey(SQLITE_DATA)) {
/*Extract Hashmap containing video game's data*/
HashMap<String, String> contentProviderBundle = (HashMap<String, String>) getArguments().getSerializable(SQLITE_DATA);
/*Set VideoGame's values*/
videoGame = new VideoGame(contentProviderBundle.get(VideoGame.KEY_UNIQUE_ID),
contentProviderBundle.get(VideoGame.KEY_CONSOLE),
contentProviderBundle.get(VideoGame.KEY_TITLE),
contentProviderBundle.get(VideoGame.KEY_LICENSEE),
contentProviderBundle.get(VideoGame.KEY_RELEASED),
Integer.valueOf(contentProviderBundle.get(VideoGame.KEY_COPIES_OWNED)));
/*Express user has not indicated ownership of any components*/
videoGame.setValueGame(false);
videoGame.setValueManual(false);
videoGame.setValueBox(false);
} else if (getArguments().containsKey(FIREBASE_DATA)) {
/*Handles editing a collected item*/
videoGame = new VideoGame();
for (String key : getArguments().keySet()) {
if (key == VideoGame.KEY_COMPONENTS_OWNED) {
/*Extract serialized HashMap*/
videoGame.setValuesComponentsOwned((HashMap<String, Boolean>) getArguments().getSerializable(VideoGame.KEY_COMPONENTS_OWNED));
}
switch (key) {
case VideoGame.KEY_UNIQUE_NODE_ID:
videoGame.setValueUniqueNodeId(getArguments().getString(VideoGame.KEY_UNIQUE_NODE_ID));
break;
case VideoGame.KEY_CONSOLE:
videoGame.setValueConsole(getArguments().getString(VideoGame.KEY_CONSOLE));
break;
case VideoGame.KEY_TITLE:
videoGame.setValueTitle(getArguments().getString(VideoGame.KEY_TITLE));
break;
case VideoGame.KEY_REGION_LOCK:
videoGame.setValueRegionLock(getArguments().getString(VideoGame.KEY_REGION_LOCK));
break;
case VideoGame.KEY_NOTE:
videoGame.setValueNote(getArguments().getString(VideoGame.KEY_NOTE));
break;
default:
Log.i(LOG_TAG, "Case 'default' is running");
break;
}
}
}
}
}
/*Inflate the layout to use as dialog or embedded fragment*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_collectable_dialog, container, false);
/*Set string for Toolbar's title*/
String toolbarTitle = setToolbarTitle();
/*Find Toolbar*/
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
/*Sets toolbar as ActionBar*/
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
/*Set toolbar's title*/
toolbar.setTitle(toolbarTitle);
/*Enable home button and supply a custom icon*/
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
/*Show custom drawable for up icon*/
actionBar.setHomeAsUpIndicator(R.drawable.ic_clear_black_24dp);
actionBar.setDisplayHomeAsUpEnabled(true);
}
/*Initialize views*/
noteEditText = (CustomEditText) view.findViewById(R.id.activity_collectable_customedittext_notes);
handleButtons(container);
/*Populate views if possible*/
if (videoGame.getValueRegionLock() != null) {
clickRegionLock(videoGame.getValueRegionLock());
}
if (videoGame.getValueNote() != null && videoGame.getValueNote() != "") {
populateNote(videoGame.getValueNote());
}
int componentsClicked = clickComponentsOwned();
Log.i(LOG_TAG, componentsClicked + " componenets were clicked");
/*Report that this fragment would like to participate in populating the options menu by
receiving a call to onCreateOptionsMenu(Menu, MenuInflater) and related methods.*/
setHasOptionsMenu(true);
return view;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
/*Causes dialog to cover whole screen*/
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
/*Inflates activity_collectable_dialog_menu as the actionbar*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.activity_collectable_dialog_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.activity_collectable_dialog_action_save:
if (videoGame.getValueUniqueNodeId() == null) {
setDate();
setNote();
videoGame.createNode();
/*Updated number of copes owned*/
int updatedCopies = videoGame.getValueCopiesOwned() + 1;
/*Key value pair used for updating database*/
ContentValues sqliteUpdate = new ContentValues();
sqliteUpdate.put(VideoGamesEntry.COLUMN_COPIES_OWNED, String.valueOf(updatedCopies));
/*Update SQLite database*/
int rowsUpdate = getContext().getContentResolver().update(VideoGamesEntry.CONTENT_URI, sqliteUpdate,
VideoGamesEntry.COLUMN_UNIQUE_ID + "=" + videoGame.getValueUniqueID(),
null);
Log.i(LOG_TAG, "Rows updated: " + rowsUpdate);
} else {
setNote();
videoGame.updateNode();
dismiss();
break;
}
case android.R.id.home:
// Make sure to confirm discard of data if data was input
dismiss();
break;
}
return super.onOptionsItemSelected(item);
}
/*Head method for handling the dialog's buttons*/
private void handleButtons(ViewGroup container) {
/*Initialization of every ImageView on activty_add_collectable_dialog.xml for programmatic use*/
usaFlag = (ImageView) view.findViewById(R.id.activity_collectable_image_usa);
japanFlag = (ImageView) view.findViewById(R.id.activity_collectable_image_japan);
euFlag = (ImageView) view.findViewById(R.id.activity_collectable_image_european_union);
game = (ImageView) view.findViewById(R.id.activity_collectable_image_game);
manual = (ImageView) view.findViewById(R.id.activity_collectable_image_manual);
box = (ImageView) view.findViewById(R.id.activity_collectable_image_box);
setImageResources();
/*ArrayList of all icons*/
ArrayList<ImageView> imageViews = new ArrayList<>();
imageViews.add(usaFlag);
imageViews.add(japanFlag);
imageViews.add(euFlag);
imageViews.add(game);
imageViews.add(manual);
imageViews.add(box);
setButtonTintInactive(imageViews);
setRegionLock(usaFlag, japanFlag, euFlag);
setCartridgeIcon();
setComponentsOwned(game, manual, box);
}
/*Set image resource for all ImageViews except R.id.activity_collectable_image_game*/
private void setImageResources() {
usaFlag.setImageResource(R.drawable.flag_usa);
japanFlag.setImageResource(R.drawable.flag_japan);
euFlag.setImageResource(R.drawable.flag_european_union);
manual.setImageResource(R.drawable.video_game_manual_icon);
box.setImageResource(R.drawable.box_icon);
}
Dialog Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorDarkBackground"
android:paddingBottom="16dp">
<include
android:id="@+id/activity_collectable_dialog_toolbar"
layout="@layout/toolbar_actionbar" />
<com.example.android.gamecollector.customviews.CustomTextView
android:id="@+id/activity_collectable_text_region_lock"
xmlns:roboto="http://schemas.android.com/apk/com.example.customviews.CustomTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/activity_collectable_dialog_toolbar"
android:layout_marginLeft="24dp"
android:text="@string/region_lock"
android:textSize="16sp"
android:textColor="@color/colorDarkPrimaryText"
roboto:typeface="roboto_bold.ttf" />
<ImageView
android:id="@+id/activity_collectable_image_usa"
android:layout_width="30dp"
android:layout_height="24dp"
android:layout_below="@id/activity_collectable_text_region_lock"
android:layout_marginTop="36dp"
android:layout_marginLeft="40dp"
android:tint="@color/colorInactiveIcon" />
<ImageView
android:id="@+id/activity_collectable_image_japan"
android:layout_width="36dp"
android:layout_height="24dp"
android:layout_below="@id/activity_collectable_text_region_lock"
android:layout_toRightOf="@id/activity_collectable_image_usa"
android:layout_marginTop="36dp"
android:layout_marginLeft="36dp"
android:tint="@color/colorInactiveIcon" />
<ImageView
android:id="@+id/activity_collectable_image_european_union"
android:layout_width="33dp"
android:layout_height="24dp"
android:layout_below="@id/activity_collectable_text_region_lock"
android:layout_toRightOf="@id/activity_collectable_image_japan"
android:layout_marginTop="36dp"
android:layout_marginLeft="36dp"
android:tint="@color/colorInactiveIcon" />
<View
android:id="@+id/activity_collectable_divider_1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/activity_collectable_image_usa"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:layout_marginRight="24dp"
android:layout_marginLeft="24dp"
android:background="@color/colorDarkDividers"/>
<com.example.android.gamecollector.customviews.CustomTextView
android:id="@+id/activity_collectable_text_components_owned"
xmlns:roboto="http://schemas.android.com/apk/com.example.customviews.CustomTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/activity_collectable_divider_1"
android:layout_marginBottom="24dp"
android:layout_marginLeft="24dp"
android:text="@string/components_owned"
android:textSize="16sp"
android:textColor="@color/colorDarkPrimaryText"
roboto:typeface="roboto_bold.ttf" />
<!--Cartridge icon will be programmatically chosen-->
<ImageView
android:id="@+id/activity_collectable_image_game"
android:layout_width="36dp"
android:layout_height="24dp"
android:layout_marginLeft="40dp"
android:layout_below="@id/activity_collectable_text_components_owned"
android:tint="@color/colorInactiveIcon"
tools:src="@drawable/gameboy_cartridge_icon"/>
<ImageView
android:id="@+id/activity_collectable_image_manual"
android:layout_width="22dp"
android:layout_height="24dp"
android:layout_marginLeft="36dp"
android:layout_below="@id/activity_collectable_text_components_owned"
android:layout_toRightOf="@id/activity_collectable_image_game"
android:tint="@color/colorInactiveIcon"/>
<ImageView
android:id="@+id/activity_collectable_image_box"
android:layout_width="23dp"
android:layout_height="24dp"
android:layout_marginLeft="36dp"
android:layout_below="@id/activity_collectable_text_components_owned"
android:layout_toRightOf="@id/activity_collectable_image_manual"
android:tint="@color/colorInactiveIcon"/>
<View
android:id="@+id/activity_collectable_divider_2"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/activity_collectable_image_game"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:layout_marginRight="24dp"
android:layout_marginLeft="24dp"
android:background="@color/colorDarkDividers"/>
<com.example.android.gamecollector.customviews.CustomTextView
android:id="@+id/activity_collectable_text_notes"
xmlns:roboto="http://schemas.android.com/apk/com.example.customviews.CustomTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/activity_collectable_divider_2"
android:layout_marginBottom="8dp"
android:layout_marginLeft="24dp"
android:text="@string/notes"
android:textSize="16sp"
android:textColor="@color/colorDarkPrimaryText"
roboto:typeface="roboto_bold.ttf" />
<!--Make sure hint and typed text have appropriate typeface, weight, size, and color-->
<com.example.android.gamecollector.customviews.CustomEditText
android:id="@+id/activity_collectable_customedittext_notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/activity_collectable_text_notes"
android:layout_marginRight="24dp"
android:layout_marginLeft="40dp"
android:hint="@string/notes_hint"/>
</RelativeLayout>
Upvotes: 0
Views: 320
Reputation: 110
Scale your drawables for screen sizes and put them in drawable-hdpi
drawable-mdpi
drawable-xhdpi
etc. folders. U can use this source. Check memmory allocation tracking
for these methods. setImageResource
should take max of about 0,5 MB memory per image. Add tints
for ImageViews
programatically after default setImageResource
.
Upvotes: 1