Handling arraylists created in a custom class (newbie confusion) - android

Basically, I need to add items to the arraylist. Am I correct in using a separate class (this is in part what I am practicing here) or is that a stupid idea because it is basically just an arraylist. I thought I would create a class because I want to randomise additions to it, etc. Alternately, since it is just an arraylist class, should I use "extends arraylist" or something similar??? Code examples most welcome. I am obviously missing some crucial programming theory here. Thank you.
NOTE I have removed what I think is unrelated code
I have a main:
public class cgame2 extends Activity {
private ArrayList<Integer> cToChooseFromImages; // clear image list
colourlist colourlistused = new colourlist();
colourlist userscolourlist = new colourlist();
....truncated....towards the end of my code I have......
colourlistused.randomaddnewitem();
And I have a class (called colourlist):
import java.util.ArrayList;
import java.util.Random;
import android.util.Log;
public class colourlist {
private ArrayList<Integer> clist;
private int picked;
int imagetodisp;
public colourlist() {
}
public void randomaddnewitem() {
Random randomtouse = new Random(System.nanoTime());
picked = randomtouse.nextInt(3);
clist.add(picked); // this is where the program crashes according to log info
}
public void addnewitem(int itemtoadd) {
clist.add(itemtoadd);
}
.....etc.....

If you're adding functionality to ArrayList, the best way is just the way you have done it.
Create a member ArrayList of your class and create functions to extend the behavior. This is called Composition.
Contrast with Inheritance, or creating a subclass of ArrayList, which can create more problems by unnecessarily coupling your implementation to ArrayList.
Don't forget to initialize the list. The best way would be:
List<Integer> clist = new ArrayList<Integer>();
Use the interface List to make your code more flexible if you choose to change the specific list implementation later.

Creating a class for your array list isn't a bad idea, classes in and of themselves are data structures, and this will allow to manipulate the data easier. By having the array list in it's own class, you will be able to get it, set it, send it, alter it, etc, with ease. However, when it comes to creating classes, you generally want to create classes that could be considered objects. If you are a beginning programmer, I would recommend exploring and researching object oriented analysis and design, as that will help you determine what should and shouldn't be classes.
And, as others have pointed out, make sure you initialize your array list:
List<Integer> clist = new ArrayList<Integer>();
As for extending ArrayList vs. List, I would use ArrayList because 1. It has all the methods and functionality of List (because is is an implementation of List) and 2. It is backed by an array, which is what you are using. Just my preference, feel free to do some research and figure out what is going to work best for what you need; a List may be all you need, in which case, you should use that.
One other things I will point out, since it looks like you are creating a game, is that if you are going to pass and object, in your case and ArrayList, you are going to want to get familiar with the Parcelable interface. It is what will allow you to pass data from one activity to another. Here is a link that will get you started, along with a tutorial that might offer some insight to what is needed:
Tutorial for Parceleable:
http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/
Developer Info:
http://developer.android.com/reference/android/os/Parcelable.html
Best of luck!

Related

Fill ListView With Items From Previous Activity

I'm new to Android programming, and still teaching myself to code.
Currently I'm teaching myself about GridViews and still coding that project with tutorials so I have nothing to show right now, but the basic idea is the following...
If I have images of groceries in GridView in the first activity and when you click an image you will be able to open a new activity with a larger image and you could input the number how many you things you need, like 5 apples or whatever.
All of that is more or less clear to me how to do.
But how would I send the number and image to a new (third) activity with a ListView that would list all the items you need to buy at the grocery store? How would I be able to fill the list only with items after you enter the number on the previous activity with the large picture and click an "OK" or "Add" button or whatever and not list absolutely everything?
Thanks!
It's difficult at first, but you can use an SQLiteDatabase to store the data.
It's not a quick solution for you, but definitely worth learning about if you're serious to learn android. Here's a link to the official stuff:
https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
I personally used this tutorial:
http://www.androidwarriors.com/2016/02/android-sqlite-database-tutorial-sqlite.html?m=1
Sharing some data between multiple activities or fragments is a very common situation. One way around it is implementing a Singleton Pattern.
In your case you can design some kind of data structure for your purpose and manage it inside shared singleton class. For example something like this:
public class ShoppingListManager {
private static ShoppingListManager instance = new ShoppingListManager();
private List<ShoppingItem> shoppingList;
public static ShoppingListManager getInstance() {
return instance;
}
public List<ShoppingItem> getShoppingList() {
return shoppingList;
}
public void addShoppingItem(ShoppingItem item) {
this.shoppingList.add(item);
}
...
// Make the constructor private so that this class cannot be instantiated
private ShoppingListManager(){
shoppingList = new ArrayList<String>();
}
}
Then you can access your data anywhere in your code and manage shared data in any way you'd like.
ShoppingListManager.getInstance().getShoppingList();
// You can add items in any activity
ShoppingListManager.getInstance().addShoppingItem(item);
One point to remember never store context in singleton classes as it will lead to memory leaks.

Displaying settings internally represented with sections in Android Listview

I'm writing an application for iOS and Android in parallell and I am facing a small problem.
I am displaying a list of settings to the user and the settings data is internally represented in settings for section, like this:
Section
Section object
Section object
Section
Section object
etc.
In iOS, when the user clicks a setting object, or when the system wants to paint the view for it, it calls a method with an NSIndexPath object. For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
and the sections are handled automatically.
In Android, the listviews are "flattened", lacking better terminology. So that a method is called only with a row index:
public Object getItem(int position);
Now it is actually a quite hard problem to solve trying to represet sections directly in the Adapter (MySettingsAdapter extends BaseAdapter).
Right now this problem is solved by flattening the entire underlaying data structure, but it's a lot of duplicated code for almost nothing. The nicer solution I can think of is to do something like the following in my MySettingsAdapter:
class MySettingsAdapter extends BaseAdapter {
MyInternalDataStructure settingsData;
int sections;
int rowsForSection[sections];
public MySettingsAdapter (MyInternalDataStructure settingsData) {
this.settingsData = settingsData;
this.sections = settingsData.sections;
for (int i = 0; i < sections; i++) {
rowsForSection[i] = settingsData.settingsInSection[i].size();
}
}
#Override
public Object getItem(int position) {
int sectionFromPostion;
int rowFromPosition;
// Calculate section and row here...
return settingsData.getSetting(sectionFromPostion, rowFromPosition);
}
}
And I just can't get the calculations for sectionFromPostion and rowFromPostion right...
Unfortunately Android does not have quite the same ability in regards to sections as you can achieve with the UITableView. However Android does provide a solution, the ExpandableListView. While similar to a ListView it works a bit differently and interacts with a different type of adapter.
Android provides the SimpleExpandableListAdapter that you can use with the ExpandableListView. I'll warn you now. It's clunky and pretty restricting. Additionally, it requires you to organize your data into a List of Maps which in itself can be a pain to do.
Alternatively, you can create your own adapter for the ExpandableListView by implementing the BaseExpandableListAdapter. It's very similar to implementing the BaseAdapter. It just has a few extra bells and whistles to support a tier like structure.
Basically all these Expandable...[foo] classes introduce the idea of having a group (the section) and children (the data under a section). Instead of having an index to the data in your adapter, you'll have a groupPosition and a childPosition. Meanwhile the ExpandableListView has this sorta murky middle notion of positions as it works with group/child positions, packed positions, and flattened positions.
As a side note. Depending on how your data is organized, I'd suggest checking out the Rolodex Adapters found in this 3rd party library. They are meant to make working with ExpandableListViews easier and has plenty of code examples and a demo app to help get you going.

Restoring an ArrayList of custom objects

In my app (which is a game), I have an 'Enemy' class, for example like so:
public class Enemy extends Sprite implements Serializable {
public Enemy(EnemyType type){
super();
}
}
I have then declared an ArrayList like so:
ArrayList<Enemy> enemyList = new ArrayList<Enemy>();
To which I can add enemies:
enemyList.add(bird);
enemyList.add(bee);
When saving to the Bundle I simply put:
bundle.putSerializable("Enemies", enemyList);
And when restoring from the Bundle, I have this:
enemyList = (ArrayList<Enemy>) savedState.getSerializable("Enemies");
Now, it does seem to restore the arraylist (I can check it's size and it is always correct - ie, the same size on restoring from the bundle, as it was when saving to the bundle.
I have also logged for example, the first index of the ArrayList and sure enough it lists the enemy instance as being there.
However, if I try to manipulate the ArrayList at any time post-restoration, I get an exception telling me that I'm trying to perform [whatever action] on a Null object (enemyList).
If I simply populate the list myself, so have something like:
enemyList = (ArrayList<Enemy>) savedState.getSerializable("Enemies");
enemyList.add(bird);
enemyList.add(bee);
Then everything works as expected.
I'm assuming this has something to do with the fact that the super class of Enemy isn't serialised? However, if I serialise this, I get a 'notSerializableException' error.
Please note, I'm not really too worried about saving/restoring the actual Enemy objects to the Bundle, I can handle this manually. Rather I just want the list to be in the same state as it was. And I thought that what was stored in the ArrayList were just references to the objects in question, therefore I can't work out why this is happening?
Any ideas what I'm doing wrong or is there a better method to achieve that which I'm trying to achieve?
The recommended way of doing this in Android is to make the objects you want to persist to be Parcelable. This is a type of serialization specific to Android.
Have a look at the official documentation here

declare Array adapter in the non-activity class to use in the fragment

So here is my problem. I'm using a dialog fragment to display some info. In that fragment, i have a spinner view that is filled up by the Array list. Normally I create that adapter in my fragment like this:
ArrayAdapter<String> teamsAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item, Variables.teamNames);
teamsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Variables.spinner.setAdapter(teamsAdapter);
Variables is my user-defined class where I keep all variables.
Now here is my question. I have around 10 DialogFragments and almost all of them have spinner. I would like to define that Adapter in my Variables class and whenever i need it, i would just call it from my variables class. Unfortunately to do that, i need getActivity() in my adapter constructor. I cannot go around it.
BTW, is it a good idea or I should use interface?
It would be awesome if somebody could actually tell me why would I use java interface in android?
Your fragment would still need to call some Variables method to retrieve the spinner and to add it to your layout, right? So when you do that call, you can pass the Activity as Context, something like this:
ArrayAdapter<String> teamsAdapter = Variables.getAdapterForTeams(getActivity());
The question about the Interface isn't an Android but a Java question. If it makes sense to use an Interface in Java it will make sense to use it in Android. There's plenty of literature and online resources about Java that will explain the why and when Interfaces should be used. I'm sure if you search online you'll find plenty of resources about it.

Android: Map of ArrayList's

I use a custom list adapter and ArrayList for my ListView. This solution was good enough but now I need to use Map of ArrayLists, something like this:
TreeMap<String, ArrayList<ItemsModel>>
where ItemsModel is a Java bean. Earlier I used to populate this ArrayList it that way:
itemsDataArrayList.add(itemModel)
Now I faced some difficulties with Map interface. First, I don't know how to populate my new Map structure: I suppose this
mapInstance.put(itemModel.getItemName.toString(), itemsDataArrayList)
won't work because itemsDataArrayList is the list of elements, not a certain element.
Second, I'm not sure how to properly declare this map instance in my ItemsAdapter class. When I was using just ArrayList it was very simple. Some examples would be very helpful.
What I recommend you look into / try is creating your own BaseAdapter. When you override this class it will give you all the functions you need to override to populate the list view.
This has the advantage of giving you complete control of what is put into the listview and how each view is created.
Then after you get it working I recommend looking into the ViewHolder design pattern along with recycling views which is a great way of improving efficiency when scrolling the listview.
What you are really looking for seem to be a MultiMap. To your first Question - your attemp was quite good, you can only put ArrayLists as values into your TreeMap.
The Problem with this might be, that if you want to add some ItemsModel to your Map, you first need to get the List of the key, and then add the ItemsModel to that list. Additionally you need to ensure, that this list for this particular key exist, and if not, create it.
Example:
String key = "hi";
ArrayList keyList = mapInstance.get(key);
if (keyList == null) {
keyList = new ArrayList();
mapInstance.put(key, keyList);
}
keyList.add(itemsModelInstance);
A get()/contains() and so on may be somehow equal. I'd suggest you build your own Multimap<?,?> Implementation or just take an existing one, like the one from Guava (link above).
Kind regards,
avi

Categories

Resources