I am retrieving the information I need here.
getStatus
public java.util.List<Status> getStatus(int limit)
throws EasyFacebookError
Throws:
EasyFacebookError
how do I set the List<Status> I retrieve to a list in android?
EDIT Here is what i am using to reteive the the status...
List<Status> status;
try {
status = rest.getStatus(10);
} catch (EasyFacebookError e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
How do i set this to a arrayAdapter?
What do you mean a "list in android"? It's giving you a list that you can use already.
To understand what the <Status> part means, you need to understand generics.
Generics allow you to have methods that take and return the type you need, rather than dealing with possible exceptions or accidentally putting the wrong type into a list.
Without generics, List's methods (it's an interface that things such as ArrayList or LinkedList happen to implement) would look like this (only some methods shown):
boolean add(Object object);
boolean add(int location, Object object);
Object get(int location);
boolean contains(Object object);
Everything is an Object and you could for example, put in anything or get out anything.
If you use a generic List, everything is of type Status instead:
boolean add(Status object);
boolean add(int location, Status object);
Status get(int location);
boolean contains(Status object);
You can then just use your retrieved list and do the following to check if size > 0 and get the first status, as an example (I have no experience with the Facebook API itself so you may have to do something entirely different than this for what you actually need):
if (list.size() > 0) {
Status myStatus = list.get(0);
}
You don't have to worry in this case that list.get(index) doesn't return a Status.
You can definitely pass this list to anything that says it accepts a List, for example an ArrayAdapter.
Check out generics, interfaces, and Android's java.util.List interface for more info on each of those things!
UPDATE
To set this list to an ArrayAdapter, ArrayAdapter has a constructor just for this:
List<Status> status;
try {
status = rest.getStatus(10);
ArrayAdapter<Status> arrayAdapter = new ArrayAdapter<Status>(context, R.layout.list_layout_name, R.id.list_item_textbox, status);
listView.setAdapter(arrayAdapter);
} catch (EasyFacebookError e1) {
// TODO Handle possible errors, of course!
e1.printStackTrace();
}
Notice ArrayAdapter is also generic. You are going to need to make an XML layout file with a TextView element that has the ID you set in the second resource argument. If you just want what the default layout, you use the two parameters android.R.layout.simple_list_item_1, android.R.id.text1. context is most likely this if you are inside an extended Activity class, or if not, you would pass a reference of the instance of your activity instead.
See you just pass the list right into the ArrayAdapter!
Note you might want a more complex adapter for more complex views, in which case you would have to subclass an Adapter and override the getView to do whatever with the Status elements. An ArrayAdapter will just put Status.toString() into the specified item text view, which may or may not be what you want.
Related
I'm working on an app in android studio. The part of the app I'm having issues with is where the user can favourite and remove their favourite item. I do this by adding and removing the item from a list.
The thing is the add functionality works which is:
public void addFavorite(Context context, NewSubject subject) {
List<NewSubject> favorites = getFavorites(context);
if (favorites == null)
favorites = new ArrayList<NewSubject>();
favorites.add(subject);
saveFavorites(context, favorites);
}
I am passing in an object of type "NewSubject" which is just a class of getters and setters for name and id.
The problem arises when I try to remove an item from this list. Code below:
public void removeFavorite(Context context, NewSubject subject) {
ArrayList<NewSubject> favorites = getFavorites(context);
if (favorites != null) {
favorites.remove(subject);
saveFavorites(context, favorites);
}
}
I've even tried something like:
for(int i = 0; i < favorites.size(); i++){
if(favorites.get(i).getSubject_name() == subject.getSubject_name())
favorites.remove(i);
}
Even though both subject names match, the if statement never triggers as true. By changing it to ID it does remove the item but I was wondering why it doesn't work the other way. MeetTitan suggested to use "equals" operator to compare Strings and this has fixed that issue. But I'm still wondering as to why removing the item by "subject" without the FOR loop and IF statement doesn't work.
I have cleared the app's data multiple times whilst trying to debug the source of the problem.
Thank you for your time and help, it is much appreciated.
This applies if you are re-creating NewSubject twice... If you are trying to remove the exact same instance of NewSubject that you got from the collection, then I guessed wrong and this isn't the answer you are looking for.
Is it possible you haven't defined equals and hashCode in your Favorites object? Without those remove will only work with the EXACT same object instance in the collection. If you haven't, try defining them and see if remove() works the way you expect.
Without those methods defined, collections will respond this way:
Obj x=new Obj("data")
Obj y=new Obj("data")
collection.put(x)
collection.remove(y)
assert( collection.size() == 1) // was not removed because .equals didn't exist--remove reverted to == instead which failed, x != y
collection.remove(x)
assert( collection.size() == 0) // NOW it worked because you used the same instance.
if you define .equals and hashCode to compare the strings inside obj, then this will work:
collection.put(x)
collection.remove(y)
assert( collection.size() == 0) // worked because x.equals(y)!
Try
String.equalsIgnoreCase(value1,value2)
This might do your work.
From your example, it's evident that name is a String object. In java, you have to use ".equals()" or comparing two strings.
You can do this:
if(favorites.get(i).getSubject_name().equals(subject.getSubject_name())){
...
}
Or, you can override the equals() method in your NewSubject class to make this work:
favorites.remove(subject);
You can use something like this as your equals() method in the NewSubject class (considering you are only matching two NewSubject objects based on their names):
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
NewSubject otherSubject = (NewSubject) other;
if(this.getSubject_name().equals(otherSubject.getSubject_name()))
return true;
else
return false;
}
Update:
You may want to override hashcode() as well. If your NewSubject class ever gets used in a hash-based collection such as HashMap, overriding only equals() method will not be sufficient. For reference, this is from Effective Java by Joshua Bloch:
You must override hashCode() in every class that overrides equals().
Failure to do so will result in a violation of the general contract
for Object.hashCode(), which will prevent your class from functioning
properly in conjunction with all hash-based collections, including
HashMap, HashSet, and Hashtable.
I have an array of Users in a class, under the column "likers"
I want to check whether or not the current user is contained in the likers array, in minimal time
This is my current (dysfunctional) code:
ArrayList<ParseUser> likers = (ArrayList<ParseUser>) rating.get("likers");
Boolean contained = likers.contains(ParseUser.getCurrentUser()) //always returns false
How can I change it to make it work? I feel it's a match on ObjectId. Maybe there is a function in the Parse SDK?
Thanks!
You can use next approach.
ParseObject rating = ParseObject.create(ParseObject.class);
ArrayList<ParseUser> likers = (ArrayList<ParseUser>) rating.get("likers");
Boolean contained = containsUser(likers, ParseUser.getCurrentUser());
Method
private boolean containsUser(List<ParseUser> list, ParseUser user) {
for (ParseUser parseUser : list) {
if (parseUser.hasSameId(user)) return true;
}
return false;
}
Little bit about your code. It works correct, return false. Because ArrayList implements the List Interface. If you look at the Javadoc for List at the contains method you will see that it uses the equals() method to evaluate if two objects are the same. Result of rating.get("likers") contains same ParseUsers as ParseUser.getCurrentUser, but they are different objects at memory. So you need find it by comparing ObjectId from Parse.com.
I have a HomeActivity which extends Activity that contains Actionbar items. The HomeActivity has 1 fragment (StatusFragment which extends Fragment). In the Fragment there is a ListView which uses a custom ArrayAdapter and a method call to supply the data.
private ParseUser[] GetUsers(){
final ParseQuery<ParseUser> query = ParseUser.getQuery();
ParseUser[] usersArray;
try {
List<ParseUser> users = query.find();
usersArray = users.toArray(new ParseUser[users.size()]);
} catch (ParseException e) {
usersArray = null;
e.printStackTrace();
}
return usersArray;
}
I'm having trouble getting the ListView to update from the OnOptionsItemSelected callback.
case R.id.home_ab_refresh:
StatusFragment pFrag = (StatusFragment) getFragmentManager().findFragmentByTag("mFragment");
pFrag.users = pFrag.GetUsers();
pFrag.mAdapter.notifyDataSetChanged();
return true;
1) Is this an appropriate way to access the Fragment from the Actionbar items (HomeActivity)?
2) Is there a better way to design this code?
Thanks much!
Re 1) I probably wouldn't do a findFragmentByTag() every time, and instead just stick the fragment into a member variable of the activity during the activity's onCreate().
The main issue with the code is something else:
pFrag.users = pFrag.GetUsers();
pFrag.mAdapter.notifyDataSetChanged();
Here you violate the object-oriented design principle of loose coupling. The HomeActivity is too intimately bound to the implementation details of the StatusFragment. What you should do instead is move that code into the fragment and expose it as a single, public method that is named for the intent (goal, purpose) of the action, not its implementation.
// In HomeActivity
pFrag.reloadData();
// In the fragment
public void reloadData() {
this.users = pFrag.GetUsers();
this.mAdapter.notifyDataSetChanged();
}
This way, it's easier to reuse the status fragment elsewhere. More importantly, it's easier to evolve that fragment, you can now completely change the internals without having to change the host activity. This is cleaner from a design perspective.
Re 2) Aside from the issue I already mentioned, you should consider returning an empty array rather than null when an exception occurs. It's generally a better idea to return empty array/collection from finder methods, because people tend to immediately use the result for an iterator or an addAll() or something like that, without null-checking it first.
First of all, you dont make a nullpointer check, since you cant be certain that the FragmentManager will actually return a validFragment.
you can however just catch the onOptionsMenuSelected event in the fragment itself, which will result in a much more capsulated code.
Besides that, when do you refresh the ListView? Wouldnt it make sense to update the listview automatically once the new data has arrived?
I'm struggling implementing a custom validator in my Android app.
I want to show in a list view some suggestions retrieved from a server (which works correctly) even if the don't start with the same letters of the text in my AutoCompleteTextView.
So, i.e. if I write "n" i'd like to get the server response, wich is "r".
So, i tried to implement a validatore setting up the isValid sample which controls if the server response is not empty.
I show my code here:
autoCompleteTextView.setAdapter(adapter);
autoCompleteTextView.setValidator(new Validator());
autoCompleteTextView.performValidation();
and here Validator class:
class Validator implements AutoCompleteTextView.Validator {
public boolean isValid(CharSequence text) {
Log.v("Test", "Checking if valid: ");
int i = 0;
if (!MainActivity.interventos.isEmpty()) {
return true;
}
return false;
}
public CharSequence fixText(CharSequence arg0) {
// TODO Auto-generated method stub
return null;
}
isValid() returns me always False, but it should return me True because MainActivity.interventos is not empty.
Ps: The entire method works good if the server responses with a word which starts with the same letters as in AutocompleteTextView.
Suggestion?
Thanks in advance
I had a similar problem which I worked out using a CustomArrayAdapter with A viewHolder implements a filter to get data from server. So, you can show in AutoComplete list data you need.
And so validator is not useful and you don't need it.
Enjoy and keep me up!!
i'm curently developing app which has lots of ArraYlists and it needs to compare them with nonlist data. When i try this method fdata.contains(data2) it always returns false. ArayLists contains class named 'favdat' which looks like this:`
public class favdat {
public String product,term,note,link;
}
And Data2 is defined like this: favdat Data2=new favdat();
I have also tryed retain all method and it returns list in the size of 0.
I know that some data are equal.
So the question is how could i tell if fdata contains data2?
The default implementation to compare objects is to compare if they are the same object, so two objects with the exactly same attributes would still not be equals. What you need to do is override the hashCode and equals methods. As an example:
public int hashCode() {
return product.hashCode() * 31 + term.hashCode();
}
public boolean equals(Object o) {
if (o instanceof favdata) {
favdata other = (favdata) o;
return product.equals(other.product)
&& term.equals(other.term)
&& note.equals(other.note)
&& link.equals(other.link);
} else {
return false;
}
}
In java classnames are usually started with capitals, so it would be Favdat, and your code usually gets easier to read to keep the field declarations separate.
You need to define a method called equals(Object obj) inside favdat that will enable object comparison.
Here's a more detailed howto:
Comparing Objects in Java
Also related thread in SO, talk about how ArrayList.contains() work.