I am lost again. My object is as follows:
public class LogInfo implements Serializable{
public ArrayList<Point[][]> strokes;
public LinkedList<byte[]> codes;
public int[] times;
...
}
First of all I populate the ListView from an ArrayList of this objects. Then I select an object from the ListView, and I would like to populate new list in new fragment with fields
public ArrayList<Point[][]> strokes;
public LinkedList<byte[]> codes;
However, to create an ArrayAdapter I can't just pass an object to it (as I understand). I need to pass an array. the problem is, that I would like to pass an object previously created and selected, and then populate the list from its fields (not only strokes or codes, but both of them).
How should my ObjectAdapter class look like and what class should it extend? To select an Object from ArrayList of Objects I used:
public class LogInfoObjectAdapter extends ArrayAdapter<LogInfo>
Example (real life):
I have a lot of cars on the parking and I need to make a list of them, so I use ArrayAdapter to populate the list. After I choose one car from the list (car object) it has two arrays in it (for example broken bulbs and broken tires, but both array are same size). Now I want to will the new list with information from selected car. I hope it is clear enough. My problem is that to use ArrayAdapter I have to pass an array in the constructor, but I want to pass the whole object and inside my adapter class process it and add choosen fields to ListView
If you have an object with multiple lists, you don't need to extend ArrayAdapter, you can just extend the BaseAdapter and implement the methods needed (getCount(), getView(), etc).
public class Adapter extends BaseAdapter {
class LogInfo implements Serializable {
public ArrayList<Point[][]> strokes;
public LinkedList<byte[]> codes;
public int[] times;
}
private LogInfo mInfo;
public Adapter(LogInfo info) {
mInfo = info;
}
#Override
public int getCount() {
if (mInfo != null && mInfo.strokes != null) {
return mInfo.strokes.size();
}
return 0;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (mInfo != null) {
Point[][] p = mInfo.strokes.get(i);
byte[] b = mInfo.codes.get(i);
//create the view
}
return null;
}
}
1) Array adapter has method getItem() you can use it to get particaular item by index.
2) Make your LogInfo implements IIterable interface
http://developer.android.com/reference/java/lang/Iterable.html
public class LogInfo implements Serializable, Iterable<Point[][]>{
public ArrayList<Point[][]> strokes;
public LinkedList<byte[]> codes;
public int[] times;
public abstract Iterator<Point[][]> iterator (){
//Iterator implementation
}
Now you can use this object directly in other list whitch has following signature
public class LogInfoObjectAdapter extends ArrayAdapter<Point[][]>
Related
I have an object with a View member. So i want to pass an ArrayList of this object and i need to pass this View. I know how to implement Parcelable.
The code is something like this :
public class Variable implements Parcelable {
public View mView;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(mView)
}
public static final Parcelable.Creator<Variable> CREATOR
= new Parcelable.Creator<Variable>() {
public Variable createFromParcel(Parcel in) {
return new Variable(in);
}
public Variable[] newArray(int size) {
return new Variable[size];
}
};
private Variable(Parcel in) {
mView= (View) in.readValue(getClass().getClassLoader());
}
So I tried object method for the writeToParcel and Variable(Parcel in) methods but obviously it didn't work.
How I should do this ?
You should only implement parcelable for data objects and never for Views, the idea is to parcel/unparcel the data state to re-instantiate a given View with state.
You should also note that there is a hard set limit on the size of the buffer that a transaction can hold when you parcel your data and send it via Intent. So ideally avoid having large in-memory object being transferred via parcel (one bad example is lets say Bitmaps)
Also, implementing parcelable by hand is pretty tedious and could be error prone. I recommend using Studio's plugin or any good third party plugin for implementing Parcelable.
Hope it helps
I have created a base class for different subclasses of adapters for my list, which it has a List field with generic type. The code of the class is as below:
public class ListBaseAdapter<T> extends BaseAdapter {
private List<T> items;
#Override
public int getCount() {
if (items==null)
return 0;
return items.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
List getDataset() {
return items;
}
public void setDataset(List<T> items) {
this.items = items;
}
}
Also, below is some example of different subclasses to it:
public class UserListAdapter extends ListBaseAdapter {...}
public class AddressListAdapter extends ListBaseAdapter {...}
In the ListFragment, a ListBaseAdapter field is declared and initialised according to different type of lists shown.
public class TheListFragment extends ListFragment {
private ListBaseAdapter adapter;
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
...
switch(type) {
case 1:
adapter = new UserListAdapter();
adapter.setDataset(users); // this line of code is getting the warning of "unchecked call to member of raw type"
break;
case 2:
adapter = new AddressListAdapter();
adapter.setDataset(addresses); // this line of code is getting the warning of "unchecked call to member of raw type"
break;
}
setListAdapter(adapter);
}
}
The code is just work fine, also I know that by setting a Type to the ListBaseAdapter such as the example below will get rid of the warning:
private ListBaseAdapter<Users> adapter;
but if I'm doing so, I will have to prepare multiple adapters in the ListFragment which each with a specific type.
I am wondering if there is a way to get rid of the warning (not using Lint) but still maintain only one adapter field or am I correctly doing this way of coding?
For your example cases, you should also initialize them with a type, i.e.:
public class UserListAdapter extends ListBaseAdapter<Users> {...}
public class AddressListAdapter extends ListBaseAdapter<Address> {...}
If you want to maintain only a single reference but still be able to pass in specific types, then given the code you provided, what I'd recommend would be something along these lines:
public class TheListFragment extends ListFragment {
// You really don't even need to keep a reference to this
// since it can be retrieved with getListAdapter()
private ListBaseAdapter<?> adapter;
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
...
switch(type) {
case 1:
UserListAdapter userAdapter = new UserListAdapter();
userAdapter.setDataset(users);
adapter = userAdapter;
break;
case 2:
AddressListAdapter addressAdapter = new AddressListAdapter();
addressAdapter.setDataset(addresses);
adapter = addressAdapter;
break;
}
setListAdapter(adapter);
}
}
Provided you don't need to make future data assignments to the adapter, that will do the trick. Your field is only of type ListBaseAdapter<?>, but your local variables are of the specific type, so you can work with them directly, and then assign them to the more weakly-typed field adapter.
I am looking at some example code on Listinterface and the implementation of it using array. I don't understand the instance variable private Object items[]; // an array of list items So is it an object called items, which is an array? why doesn't it just say private array items[] ?
Also about the constructor items = new Object[MAX_LIST];does it initalise an array named item? The code is attached below. Many thanks for your help!
public interface ListInterface {
public boolean isEmpty();
public int size();
public void add(int index, Object item)
throws ListIndexOutOfBoundsException,
ListException;
public Object get(int index)
throws ListIndexOutOfBoundsException;
public void remove(int index)
throws ListIndexOutOfBoundsException;
public void removeAll();
}
public class ListArrayBased implements ListInterface {
private static final int MAX_LIST = 90;
private Object items[]; // an array of list items
private int numItems; // number of items in list
Basically, private Object items[]; is exactly equivalent to private Object[] items; -- it's just different way of writing an array of Object called items.
Object is a Generic. It can be any object including String, Integer, etc.. So here you are creating an Array of the type Object, with the size mentioned.
Better go through Oracle Java Tutorials about Arrays.
I am new to Android development and I am trying to create a ListFragment that can create a ListView from 3 ArrayList objects each containing 30 Strings. Each row would contain a string from each array.
In my reading, I have found that a ListView is essentially created from an ArrayAdapter. The only examples I've seen of this however only show 1 String[] array being used (http://goo.gl/Yrkn0k, http://goo.gl/hqkdl).
How can I pass the three arrays to ArrayAdapter to create this ListView?
ArrayAdapters can work on lists of any sort. If you need to have an ArrayAdapter operate on three separate lists at once, you will need to do two things:
Create a new object class that is the combination of the three lists, eg. an Item class that has three fields: Title, Description, Price. Once you have a suitable object, turn your three lists into a single list of your object.
Then you will need to create a custom adapter class that extends ArrayAdapter, overriding the getView method in order to properly display your items.
Edit
Example:
public class Item {
private String title, desc, price;
public Item(String title, String desc, String price) {
this.title = title;
...
}
*provide standard getters and setters*
}
...
ArrayList<Item> items = new ArrayList<Item>();
for(int i = 0; i < titles.length; i++) {
items.add(new Item(titles[i], descriptions[i], prices[i]);
}
Then new adapter should take the form of
private class CustomAdapter extends ArrayAdapter<Item> {
public CustomAdapter(ArrayList<Item> items) {
super(getActivity(), 0, items);
}
...
The ArrayAdapter<T> class is generic, so you can use it with java Collections. To do what you're trying to do, you could use an ArrayList<ArrayList<String>> or just build model objects that contain your 3 string fields and use ArrayList<YourModel>.
For Example:
public class MyAdapter extends ArrayAdapter<ArrayList<ArrayList<String>>>{
//Constructor
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ArrayList<String> current = getItem(position);
//Do Something
}
}
I have an android app with a Business Object (let's call it SuperClass) that has several derived classes (let's call them DerviedClassA, DerivedClassB etc). Each object has a constructor which takes a Cursor object with multiple rows and assigns appropriate properties based on the current row in the cursor
public Class DerivedClassA
{
// properties
private int X;
// etc
public DerivedClassA(Cursor data)
{
X = data.getInt(data.getColumIndex(ColumnX));
// etc
}
}
I then have BO methods which return an ArrayList of the derived class, like below:
public static ArrayList<DerivedClassA> getDerivedClassAList(Cursor data)
{
ArrayList<DerivedClassA> list = new ArrayList<DerivedClassA>();
for(int i=0;i<data.getCount();i++)
{
data.moveToPosition(i);
DerivedClassA wev = new DerivedClassA(data);
list.add(wev);
}
data.close();
return list;
}
And so on for DerivedClassB, DerivedClassC etc. To avoid this duplication, I want to be able to have a single method which somehow takes in the type of the derived class, invokes the appropriate constructor of that derived class, and returns an ArrayList of the appropriate derived class. Something like:
public static ArrayList<T extends SuperClass> getDerivedClassList(Cursor data)
{
ArrayList<T> list = new ArrayList<T>();
for(int i=0;i<data.getCount();i++)
{
data.moveToPosition(i);
T wev = new T(data);
list.add(wev);
}
data.close();
return list;
}
However, I'm not sure if it's actually possible, or how to go about it. Any pointers would be appreciated.
Yes, it is.
public static <T extends SuperClass> ArrayList<T extends SuperClass> getDerivedClassList(Cursor data)
{
ArrayList<T> list = new ArrayList<T>();
for(int i=0;i<data.getCount();i++)
{
data.moveToPosition(i);
T wev = new T(data);
list.add(wev);
}
data.close();
return list;
}
Refer:
http://download.oracle.com/javase/tutorial/extra/generics/methods.html
http://download.oracle.com/javase/tutorial/java/generics/genmethods.html