In my Android Application I've some objects which represent different kinds of operations.
public class OperacionDivisa implements IOperacion {
public class OperacionLargo implements IOperacion {
public class OperacionMedio implements IOperacion {
public class OperacionOpciones implements IOperacion {
Each kind of operation implements IOperation interface so I can make an ArrayList of IOperations and store all operations in a single ArrayList.
Now I'd like to do the inverse process. I want to get the arraylist of operations from Firebase (which has already been achieved) and I'd like to show the operations in a ListView
I created a custom adapter as follows:
public class ListViewAdapterOperaciones extends ArrayAdapter<IOperacion>
The issue is that I need to cast each object to its original class to show in a textview different attributes. So this is not useful.
IOperacion operacion = (IOperacion) getItem(position);
So, for each object I'd like to show some data in the listView but I haven't been able to figure out how to do this. Any help would be appreciated.
Thanks in advance.
Use an if statement (or similar) to check instanceof, then use the objects as the subclass.
if (operacion instanceof OperacionLargo) {
// Large operation
} else if (operacion instanceof OperacionDivisa) {
// Other operation
}
Related
I seem to be stuck with a problem with an object communicating with my activity class. The object is a view object with an onClick method that when called I would like it to notify my activity class so that it can perform said action. Below is some example code of my situation (assume all conventional setup operations have already been made):
public class MainActivity extends AppCompatActivity{
//...other global methods and objects
//Does not have access to instantiated Entry object(s)
public void entryObjectWasClicked(){
//perform said action
}
}
public class Entry extends View implements View.OnClickListener{
//...other global methods and objects
//Does not have access to the MainActivity object
#Override
public void onClick(View v){
//send a message to the MainActivity to
//somehow call the entryObjectWasClicked() method
}
}
The only way (off the top of my head) that I could think about dealing with this problem is by creating a static method in MainActivity and then calling it from an anonymous MainActivity object in the onClick method of Entry. The problem with the static method approach is that any subsequent method/object/primitive usages in the static method force those methods/objects/primitives to be static. This defeats the purpose of then being able to have two different instances of the MainActivity object.
After some looking I came across using Broadcast messages, specifically using the LocalBroadcastManager to send an intent to the activity. This code example works for my model, but I want to know: is this the best way for me to go about sending messages to my MainActivity from my Entry object?
If there is a more effective way of doing all this, what would it be?
You're overcomplicating things. Don't override onClick for this. Instead, have your activity call setOnClickHandler on your view, which sets a callback that's called when the view is clicked. Then use the default implementation.
Since you extend view, i guess you want to use it inside a layout. That means you may want to create a Listener for that. Example:
public class Entry extends View implements View.OnClickListener{
private OnClickListener listener;
public void setListener(OnClickListener listener) {
this.listener = listener;
}
#Override
public void onClick(){
if (this.listener != null) this.listener.onClick(this);
}
}
How you can inflate your layout in your Activity and access your custom view.
public class MainActivity extends AppCompatActivity{
public void onCreate( ...) {
Entry entry = findViewById(R.id.entry);
entry.setListener(new OnClickListener(...));
}
}
I have an ArrayList<? extends BaseModel> that I'd like to store in Realm.
I have several classes that extend BaseModel and they're all stored in this ArrayList. Will Realm just do the right thing if I store this on disk? Each child class may have it's own additional members and methods.
I should probably just try testing this myself, but I'm away from my dev machine, so thought I'd ask anyway and answer it myself if no one gets to it first.
Thank You!
You can store list of BaseModel by call copyToRealmOrUpdate(), if BaseModel extend of RealmObject class or if implement RealmModel interface:
void storeListToRealm(List<? extends BaseModel> models) {
realm.beginTransaction();
realm.copyToRealmOrUpdate(models);
realm.commitTransaction();
}
Otherwise, you need to create "StoreModel", which you can store to realm, and mapping from BaseModel to StoreModel.
Realm generates a RealmModuleMediator class that has the following code:
public String getTableName(Class<? extends RealmModel> clazz) {
checkClass(clazz);
if (clazz.equals(com.yourpackage.somemodel)) {
return io.realm.SomeModelRealmProxy.getTableName();
} else if (clazz.equals(com.yourpackage.anothermodel)) {
return io.realm.AnotherRealmProxy.getTableName();
} else if ...
Looks to me like it makes no difference whether you pass in the subclass or the super class.
I'm developing an android application that deals with bitmaps. Right now I'm using an LRUCache to store these bitmaps, but there are going to be multiple fragments that require access to this cache. What's the best way to handle to handle a global application cache? Should I use a singleton? Should I create a new cache for each activity/fragment that requires access to it?
To avoid Singletons in Android Development, like in your question I would suggest anybody using Fragments to store real global Objects in the MainActivity. It should look like this:
MainActivity:
public class MainActivity extends FragmentActivity{
//eg a ArrayList
private ArrayList<MyObjects> mObjectContainer = new ArrayList<MyObject>();
//Do something with the list and fill it
public ArrayList<MyObjects> getObjectContainer(){
return mObjectContainer;
]
public void addObject(MyObject object){
if(!mObjectContainer.contains(object)){
mObjectContainer.add(object);
}
}
}
Fragment:
public class MyFirstFragment extends Fragment{
onCreateView(...){
//make typical Fragment init like create View
ArrayList<MyObjects> list = ((MainActivity)getActivity()).getObjectContainer();
//add a new Object
((MainActivity)getActivity).addObject(new MyObject("any data"));
}
}
I'm implementing a list which needs to be displayed by an activity and modified (add items, remove items, sort) by the user. Currently I have two different classes - the activity class and the list class which has all the operations on the list. However, the activity class is going to need access to the list in order to adapt and display it, and it seems kind of clumsy to either duplicate the list for the activity or make the list public. I get the feeling I might not be understanding what activities are correctly - should my two classes really be one single class? I assumed activities were mostly for UI, not for modifying the underlying datastructure.
Activities are the main building blocks of Android, all the different screens that you see in your Application are Activities. You should understand that not all Java Classes used in your Android App are Activities (only those Java Classes that extends Activity are Activities).
The Java Classes that are not Activity (used in your code) can be simply plain Data Models, Custom Adapters, Custom Views, Database Handlers, Services, and so on.
All these Java files are used separately from the Activity Class to provide Modularity and to avoid creating a Mess and deficiency by implementing all the Functionality in a Single Activity Class.
You use the instances of these other Java Classes (or use them statically) in your Activity Class.
For Displaying a Simple List, you can use ListView widget, and you don't really need a separate class for it's implementation. Likewise, if you are preparing to implement a ListView with functionality such as Delete, Add, Update, etc. Then Custom ListView is the alternative option that you can use.
You cannot implement a Custom List View in a single Activity Class, you will be needing a Custom Adapter Class, a Custom Data Model Class and other related classes for it's implementation.
Here is a list of some useful tutorials for implementing Simple and Custom ListViews:
Vogella's ListView Tut
The Open Tutorials
Android Example 1
Android Example 2
I hope this helps.
I'm implementing a list which needs to be displayed by an activity and modified (add items, remove items, sort) by the user.
You can do the simple operations defined by the List<T> interface like add, remove, etc. You can write a custom Comparator<T> to perform sort operations. Then use the Collections.sort() method to do your work.
Currently I have two different classes - the activity class and the list class which has all the operations on the list.
It depends. I generally prefer to make a singleton instance of the list and let my activity modify it on callbacks from ListView. There is nothing clumsy about letting your Activity handle the addition or removal from list.
However, the activity class is going to need access to the list in order to adapt and display it, and it seems kind of clumsy to either duplicate the list for the activity or make the list public.
Like I said, look up what a Singleton Instance is. Share your list across multiple activities by creating a class that has the list in it. Declare the list public. That way, you share the list and do not duplicate it. Remember: if you duplicate the data multiple times. keeping them in sync is going to be a tough nut to crack.
Think about it like that. Your oncreate is called once. If you need things done on the list, they will most probably be on your onItemClick, onItemLongClick kinda events. And when that happens, you should call a AsyncTask, coded in your same activity, so that the onPostExecute can modify its UI elements and the list. Some example below.
Note, the code below has been reduced bigtime, so excuse syntax
package com.taxeetaregistration;
public class Bookings extends ListActivity implements OnClickListener, OnItemClickListener {
private static LayoutInflater inflater = null;
private LinkedList<BookingRecord> bookingRecord;
private ListView customerList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bookings);
Log.d("Taxeeta", "Entered BookingExperience");
bookingRecord = new LinkedList<BookingRecord>();
customerList = (ListView) findViewById(android.R.id.list);
customerList.setAdapter(new CustomerList());
customerList.setOnItemClickListener(this);
getBookings = new GetBookings();
getBookings.execute();
}
public class CustomerList extends BaseAdapter implements OnClickListener {
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null || convertView.getTag() == null) {
convertView = inflater.inflate(R.layout.bookingresponse_row, null);
final CustomerViewHolder viewHolder = new CustomerViewHolder();
viewHolder.customerRow = (LinearLayout) convertView.findViewById(R.id.customerRow);
viewHolder.customerName = (TextView) convertView.findViewById(R.id.customerName);
viewHolder.customerPhoneNumber = (TextView) convertView
.findViewById(R.id.customerPhoneNumber);
convertView.setTag(viewHolder);
}
// Setting all values in listview
String temp = bookingRecord.get(position).customer.getFullName();
((CustomerViewHolder) (convertView.getTag())).customerName.setText(temp);
temp = bookingRecord.get(position).customer.getPhoneNumber();
((CustomerViewHolder) (convertView.getTag())).customerPhoneNumber.setText(temp);
return convertView;
}
public class GetBookings extends AsyncTask<Object, Integer, Object> {
#Override
protected Object doInBackground(Object... params) {
connectToServer();
//Do all network related work here, and update
publishProgress(j);
}
}
return null;
}
#Override
public void onPostExecute(Object result) {
super.onPostExecute(result);
if (bookingRecord != null && bookingRecord.size() > 0) {
busy.setVisibility(View.GONE);
((BaseAdapter) customerList.getAdapter()).notifyDataSetChanged();
} else {
progressBarUpper.setVisibility(View.GONE);
Log.d("Taxeeta", "No cabbies found");
}
}
#Override
protected void onProgressUpdate(Integer... i) {
super.onProgressUpdate(i);
boolean found = false;
customersFound.setText("" + totalCabbiesSubscribed);
BookingRecord newRecord = new BookingRecord();
newRecord.customerJourney = customerJourney;
newRecord.customer = customer;
bookingRecord.addLast(newRecord);
customersConfirmed.setText("" + bookingRecord.size());
}
}
private class CustomerViewHolder {
public LinearLayout customerRow;
public TextView customerName;
public TextView customerPhoneNumber;
public TextView customerFrom, customerTo;
public ListView cabbieList;
public float distanceFromCustomer = -1.0f;
}
public class BookingRecord {
public BookingRecord() {
cabbies = new ArrayList<CabbieDetails>();
}
public IJourneyDetails customerJourney;
public IUserDetails customer;
public SearchResultsConcrete cabbieList;
public ArrayList<CabbieDetails> cabbies;
}
}
I have a CustomAddress class that extends the android.location.Address class that implements Parcelable.
I am trying to make my CustomAddressimplement Parcelableto but am stuck when creating my class from a parcel. What I want to when creating CustomAddressfrom a parcel is first fill in all the fields from the super class Addressand then my own fields. So I have implemented the CREATORfield:
public static final Parcelable.Creator<CustomAddress> CREATOR
= new Parcelable.Creator<CustomAddress>() {
public CustomAddress createFromParcel(Parcel in) {
return new CustomAddress(in);
}
public CustomAddress[] newArray(int size) {
return new CustomAddress[size];
}
};
But in my CustomAddress(Parcel in)creator, I can't call super(in)because it doesn't exist in android.location.Address. I can only access android.location.Address.CREATOR. So how do I fill in my fields using CREATOR?
EDIT: link to the android Address class https://developer.android.com/reference/android/location/Address.html
Here is a similar question and Mark Murphy's excellent answer: https://stackoverflow.com/a/10841502/1140682
So, in your case, you would make CustomAddress extend Address (as you already do), call the super() method in the constructor and then read your own attributes from the passed Parcel. Same has to be done (in same order) in the writeToParcel() method, of course here adding your attributes to the parcel.