I have a 56 drawable in my res folder.
I use them in 2 Fragments.
Is it a good memory approach to create a class that has a static array containing those drawables and call its get method whenever I want to use it?
Or Should I create a private array in each Fragment?
you should create private arrays in the fragment. Having them all in another class will means they will never get destroyed even when your not using them taking up memory. In addition static arrays will get deleted when the app goes into the background for too long, so you would need extra code to reload the array when is resumed if the array is null
You could just create a static int array using the resource ids, here is an example:
public static final int[] DRAWABLE_ARRAY = {
android.R.drawable.sym_def_app_icon,
android.R.drawable.title_bar,
android.R.drawable.ic_menu_compass
};
Then usage of this array could be something like so:
for (int i = 0; i < DRAWABLE_ARRAY.length ; i++) {
context.getResources().getDrawable(DRAWABLE_ARRAY[i]);
}
This way you aren't creating objects that take up a decent amount of memory since these are only resources ids
Related
How can I add an image from drawables to a RecyclerView. I tried to add by using the method below:
names.add(R.drawables.image, "Image1");
but it gives me error.
Is there any alternative for adding image into the arraylist without creating another class.
Solution: Please follow.
Step1: Declare a Global Object.
public ArrayList<Integer> imgArrayList;
Step2: Initialize
imgArrayList = new ArrayList<>();
Step3: Add your Drawables in two ways.
First Way: Directly add images one by one.
imgArrayList.add(R.drawable.image1);
imgArrayList.add(R.drawable.image2);
imgArrayList.add(R.drawable.image3);
..... etc etc
Second Way: Make an array of int as shown below:
int imgList[] = {R.drawable.image1, R.drawable.image2, R.drawable.image3}
then,
imgArrayList.addAll(imgList);
That's it, Now you choose which you want to use. All the best.
To bring an image from drawables you have to have the context in the adapter so that you can use the method:
context.getDrawable(R.drawable.image)
But this will force you to send the context to the adapter or you have to use the very same method(getDrawable(R.drawable.image)) directly from inside the activity launching the adapter like that:
getDrawable(R.drawable.image)
I know that this does not sound helpful because you need the images in the adapter so
all what you have to do is preparing the images list in the activity, then send that in the constructor of the Adapter
names.add(R.drawables.image, "Image1");
Assuming names is a String ArrayList, you're trying to add "Image1" to index R.drawables.image (which is a big number, in your case 2131165305)
To fix your issue, you can create a List of Integer values and only add the drawable identifier, so
ArrayList<Integer> drawableIds = new ArrayList<>();
drawableIds.add(R.drawable.image1);
drawableIds.add(R.drawable.image2);
then set your image like
// add a for loop here or whatever
imageView.setImageResource(drawableIds.get(i));
Block Array or multidimensional array Variables. For some reason my app is throwing out of memory on my loading of my pub vars class. This started happening when I started using Block Arrays. It works on actual devices but not on the emulators. Any thoughts? Should I set my block arrays to actual needs?
Current Block Arrays:
public static String[][] Name = new String[1000][1000];
however I only use maybe 10 or so. Is the device allocating space for the potential of the 1000 and is that why it is errors out? If so, how can I use these as the need may grow and I do not want to put a small limit on it. Thanks in advance for any thoughts.
With
public static String[][] Name = new String[1000][1000];
you are allocating 1 million strings (1000x1000) which is quite a bunch. If the information on this page is correct each string at least takes 40 bytes, so that would be around 39 Mbytes in your case and this can easily be too much memory on the heap for 1 activity. I would start there to refactor if you are only using 10. There is probably a better solution than your approach but without any more details on your code it's hard to give them. But of the top of my head, why not use a Set<String> or List<String> ?
Edit: So it's seems to me that you just want a Collection that scales dynamically. For that array is not the best choice. There are many of datatypes for that but one simple example whould be an ArrayList which also uses a array as backing datatype but by default will be instanciated with a capacity of 10 and expands dynamically if you continue to add elements
List<String> stringList = new ArrayList<String>();
stringList.add("string1");
stringList.add("string2");
...
If you want each element to have its own list of strings just create an object for that:
public class CompoundString {
private String key;
private List<String> stringList;
...
}
and use it like this
List<CompoundString> compoundStringList = new ArrayList<CompoundString>();
compoundStringList.add(new CompoundString("string1", new ArrayList<String>());
or just use a map:
Map<String,List<String>> stringMap = new HashMap<String,List<String>>();
stringMap.put("string1", new ArrayList<String>());
This is pretty basic concept in most programming languages and I would start to read some docs about the various collections:
http://docs.oracle.com/javase/7/docs/api/java/util/List.html
http://docs.oracle.com/javase/7/docs/api/java/util/Set.html
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
http://www.mkyong.com/java/what-is-the-different-between-set-and-list/
I have been creating all of my layouts in the XML files. However, I am now at a point where I should port a few of the pages into my java code to programatically build them.
I have found the View.setId() function, but it is giving me errors. I have read that you can just use positive integers to id your views, but I have a whole lot of views and would like to label them properly.
I know I could create a bunch of integers in my class with names, but is there a way to use setId to create a new id that can be referenced by calling R.id.whatever?
No. R is actually a class that gets generated. You can't add to it at runtime.
You can create some class IDS and store id constants there.
public class Ids {
private Ids(){}
public static int BUTTON_OK = 0;
public static int BUTTON_CANCEL = 1;
}
and refer to those id's.
I am creating an Android board game similar to, for example, Bubble Pop where I need to use several bitmaps multiple times.
I have a list of Stones (10x10), where each Stone is an object which holds its bitmap and some other values. Lot of bitmaps (stone colors) are same.
Right now i am using something like this for every Stone in the list:
public class Stone extends Point{
private Bitmap mImg;
public Stone (int x, int y, Resources res, Stones mStone) {
...
mImg = BitmapFactory.decodeResource(mRes, mStone.getId());
}
protected void changeColor(Stones newD){
mStone = newD;
mImg = BitmapFactory.decodeResource(mRes, mStone.getId());
}
}
I found several similar questions, but it is all about big bitmaps. Also i found some Android documentation about caching images, but i am not sure if it solves my problem and how to share this cache between all my stones.
What is the best practice, to achive good performance and avoid OutofMemoryError?
You probably don't need cache. Since you should have a limited number of stone colors (thus bitmaps) you can consider holding those graphic assets in one single class (probably static global class or through singleton pattern.
In your Stone class, you just need to hold the stone's color Id and get the drawable from your assets class. (you can save bitmap, but drawable is much more efficient and you may easily change it to allow some animation later)
For example:
// Singleton - look at the link for the suggested pattern
public class GraphicAssets {
private Context mContext;
private Hashtable<Integer, Drawable> assets;
public Drawable getStone(int id){
if (assets.containsKey(id)) return assets.get(id);
// Create stone if not already load - lazy loading, you may load everything in constructor
Drawable d = new BitmapDrawable(BitmapFactory.decodeResource(mContext.getResources(), id));
assets.put(id, d);
return d;
}
}
you could make the Bitmap variable static or static final
I want to pass an array from one Activity to another Activity,for example I need to pass an array from image_view Activity to Blackimage Activity.Please give solution to this problem in Android.
Using a Singleton is probably a bad idea here, especially given Android's kill-happy lifecycle and the high likelihood of leaking Context if you do it wrong. Android has a very simple and powerful built-in message-passing capability on Intents - use it! You should pass the array as an Extra on the Intent, either using the built-in putExtra methods that take Arrays of various Java builtins, or by making sure your array is made of Serializable objects and passing it to the Intent's putExtra method that takes any serializable object. Then you can simply get the extra out of the Intent in the second Activity's onCreate(), no messy singletons necessary.
Read up on making a singleton class, then you can call singleton.setArray(myArray) in one Activity, and singleton.getArray() in the next.
If they are both in the same application.
In addition to the singleton class, you might want to look at using the Android SharedPreferences to save/get any data to either save your settings or prevent loss of data if interrupted.
Also adding android:configChanges="keyboardHidden|orientation"> into the AndroidManifest will prevent your app from losing data if you rotate screens/slide open keyboard.
SharedPref Example
String m_myData[];
Boolean m_myBoolData[];
public static void saveSettings()
{
SharedPreferences.Editor editor = m_SharedPreferences.edit();
for(int ix = 0; ix < m_myData[].length; ix++
{
editor.putString("myKey" + ix, m_myData[ix]);
editor.putBoolean("myKey" + ix, m_myBoolData[ix])
}
}
public static void getSettings()
{
for(int ix = 0; ix < m_myData[].length; ix++
{
m_myData[ix] = m_SharedPreferences.getString("myKey" + ix, false);
m_myBoolData[ix] = m_SharedPreferences.getBoolean("myKey" + ix, false )
}
}
Passing it through the activity will be the best performance choice, as if you use preferenes or the Intent to pass on the array you will have to loop over the array to persist it and recover it from the Intent or Preferences.
Using the Application will allow you to pass on the array, but doing so, just like with a singletone will force you to handle it instance being destroyed as if you wont do it it wont be GCed even after the two activities died since the application will still keep a reference to it.