I've been looking at the firebase documentation and tried to make firebase work with an android app I'm building.
All the code examples I could find show how to get a value, then immediately print it within the firebase ValueEventListener inner class. I would like to get the values and store them in an array for later use.
What I try to do is when a user clicks the highscore button the client gets the current scoreboard from firebase, and sends that list to the highscoreboard class.
UPDATE: I have been able to retrieve the data now but there is a behavior that confuses me greatly. If the user clicks the highscorebutton the scores list gets populated and highscore class is correctly showing 10 elements. If I exit the scoreboard and enter it again it will now show all scores twice (understandably so, as I am just adding to the same list). But any calls to scores.clear() or scores = new ArrayList(); between the two clicks results in scores being empty even after the second click (I assumed that populating scores, then emptying it and repopulating it would leave 10 items in there) This behavior was the reason I thought my scores array never got populate when first posting here as I had a scores.clear() call inside the load function since I didn't want to duplicate values. If anyone is able to explain why this happens that would be fantastic.
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
ArrayList<Score> scores;
Firebase myFirebase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Firebase.setAndroidContext(this);
myFirebase = new Firebase(FirebaseURL);
scores = new ArrayList<Score>();
loadScoresFromFireBase();
}
public void loadScoresFromFireBase() {
String entry = "";
for (int i = 0; i < 10; i++) {
entry = "Name_" + i;
myFirebase.child("users").child(entry).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
//getValue correctly returns a Score object
scores.add(snapshot.getValue(Score.class));
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//....
if ( id == 2) {
Intent intent = new Intent(getApplicationContext(), ScoreBoard.class);
Bundle bundle = new Bundle();
//calling scores.clear() here leaves the scores array empty even though loadscores is called afterwards.
loadScoresFromFireBase();
Collections.sort(scores);
bundle.putSerializable("players", scores);
intent.putExtra("players", bundle);
startActivityForResult(intent, 0);
}
}
}
You're falling for the classic asynchronous trap:
loadScoresFromFireBase();
Collections.sort(scores);
When you call loadScoresFromFireBase() (it's spelled Firebase btw), the program starts synchronizing the scores from the server. Loading this data takes some time. Instead of making your program wait (which would be a bad user experience), Firebase makes you pass in a ValueEventListener that it then calls when the data is available. But you're calling Collections.sort(scores) straight away, before the (first) data has been loaded.
You can most easily see this by adding a few log statements:
public void loadScoresFromFireBase() {
String entry = "";
for (int i = 0; i < 10; i++) {
entry = "Name_" + i;
myFirebase.child("users").child(entry).addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
System.out.println("Adding score to array");
scores.add(snapshot.getValue(Score.class));
}
public void onCancelled(FirebaseError firebaseError) { }
});
}
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//....
if (id == 2) {
Intent intent = new Intent(getApplicationContext(), ScoreBoard.class);
Bundle bundle = new Bundle();
System.out.println("Before calling loadScores");
loadScoresFromFireBase();
System.out.println("After calling loadScores");
Collections.sort(scores);
System.out.println("After sorting scores");
The output of these log statements will be:
Before calling loadScores
After calling loadScores
After sorting scores
Adding score to array
That is probably not what you expected. But it is completely normal when you're dealing with asynchronous/event driven code, like is common in modern internet programming.
The most direct solution is to move the code that needs the scores into the function that loads them:
public void loadScoresFromFireBase() {
String entry = "";
for (int i = 0; i < 10; i++) {
entry = "Name_" + i;
myFirebase.child("users").child(entry).addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
scores.add(snapshot.getValue(Score.class));
Collections.sort(scores);
Intent intent = new Intent(getApplicationContext(), ScoreBoard.class);
Bundle bundle = new Bundle();
bundle.putSerializable("players", scores);
intent.putExtra("players", bundle);
startActivityForResult(intent, 0);
}
public void onCancelled(FirebaseError firebaseError) { }
});
}
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//....
if (id == 2) {
loadScoresFromFireBase();
Also see this answer I wrote a while ago: Setting Singleton property value in Firebase Listener
As well as these great answers on the same problem:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
How do I return the response from an asynchronous call?
Although these are about JavaScript, they deal with the exact same problem.
As you have not initialized scores you will be getting a NullPointerException when calling add
If you do
ArrayList<Score> scores = new ArrayList ();
it should work
Related
The code for the spinner is below, The spinners on my app tend to duplicate it's content sometimes for some weird reason. How do I prevent this from happening?:
Spinner spinnerG = (Spinner) findViewById(R.id.spGroup);
final ArrayAdapter<String> dataAdapterG = new ArrayAdapter<>
(this, R.layout.simple_spinner_item, groups);
dataAdapterG.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
spinnerG.setAdapter(dataAdapterG); //general basics //sets up the group spinner, filled with the groups list
spinnerG.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
selectedGroup = groups.get(position);
studentsToShow.clear();
for(int i = 0; i < studList.size(); i++){
if(studList.get(i).getGroup().equals(selectedGroup)){
Students a = new Students();
a.setFirstName(studList.get(i).getFirstName());
a.setLastName(studList.get(i).getLastName());
a.setStudentID(studList.get(i).getStudentID());
a.setGroup(studList.get(i).getGroup());
studentsToShow.add(a); //when a new group is chosen the list of students in the selected group needs to be updated
} //this re uses the code earlier to make a list of student in the selected group
}
updateSpS(); //updates the student spinner
}
public void onNothingSelected(AdapterView<?> parent){
}
});
The spinner will duplicate if you have put this oncreate event. Put the spinner population code on the onResume method.
From the snippet shared with the question, its hard to guess why OP would have duplicate value. An educated guess is his onItemSelected() is being called multiple times.
Spinner's (in my personal view, is one of the worst android widget) onItemSelected() can be called multiple times for different reasons, one of the thing I would recommend to try this way -
class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
boolean userSelect = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
userSelect = true;
return false;
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (userSelect) {
// Your selection handling code here
userSelect = false;
if(view!=null){
selectedGroup = groups.get(position);
studentsToShow.clear();
for(int i = 0; i < studList.size(); i++){
if(studList.get(i).getGroup().equals(selectedGroup)){
Students a = new Students();
a.setFirstName(studList.get(i).getFirstName());
a.setLastName(studList.get(i).getLastName());
a.setStudentID(studList.get(i).getStudentID());
a.setGroup(studList.get(i).getGroup());
studentsToShow.add(a); //when a new group is chosen the list of students in the selected group needs to be updated
} //this re uses the code earlier to make a list of student in the selected group
}
updateSpS(); //updates the student spinner
}
}
}
}
And then set -
SpinnerInteractionListener listener = new SpinnerInteractionListener();
spinnerG.setOnTouchListener(listener);
spinnerG.setOnItemSelectedListener(listener);
This at the same time takes care unwanted callbacks of onItemSelected() without user touch and if any previous leaked listeners.
So I have a list of strings (ISBNs), and I need to fill a listview with the objects (Book objects) associated with these strings. The problem is that the function I have to get the Book object using the string takes time, and so to get, say 30 books, the wait approaches 4 or 5 seconds.
One approach I've thought of is to get the Book objects one at a time, and to add them to the list as I get them. But this process will freeze the UI until it's done adding them all. If I try to put this process in a new thread, it won't let me add to the any UI objects (since it's from another thread). If I try to put it in an AsyncTask, I can't access the ListView since it's in the MainActivity class.
There must be a way to dynamically update a UI element, I'm sure I've seen it done. Any suggestions?
EDIT:
This is the code I'm using to actually add items to the list:
//List view and adapter setup
listView = (ListView) findViewById(R.id.listViewCheckout);
bookAdapter = new SearchBookAdapter(getApplicationContext(), R.layout.search_row_layout);
listView.setAdapter(bookAdapter);
for(int i = 0; i < searches.size(); i++) {
//Get the book
Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));
//Assign data to the adapter variables
Bitmap cover = book.getCover();
String title = book.getTitle();
String author = book.getAuthor();
//Add data to the adapter and set the list
SearchBookDataProvider dataProvider = new SearchBookDataProvider(cover, title, author);
bookAdapter.add(dataProvider);
bookAdapter.notifyDataSetChanged();
}
Can you make some changes to your code like this it simple it think it will work
//List view and adapter setup
listView = (ListView) findViewById(R.id.listViewCheckout);
bookAdapter = new SearchBookAdapter(getApplicationContext(), R.layout.search_row_layout);
SearchBookDataProvider dataProvider;
listView.setAdapter(bookAdapter);
new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
for(int i = 0; i < searches.size(); i++) {
//Get the book
Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));
//Assign data to the adapter variables
Bitmap cover = book.getCover();
String title = book.getTitle();
String author = book.getAuthor();
//Add data to the adapter and set the list
dataProvider = new SearchBookDataProvider(cover, title, author);
bookAdapter.add(dataProvider);
}
}
#Override
protected void onPostExecute(Object o) {
if (bookAdapter!= null) {
bookAdapter.notifyDataSetChanged();
}
super.onPostExecute(o);
}
}.execute();
you can use TimerTask to update the listview or runUiThread() or doInBackground(). But remember should use notifysetChanges() when you update the list.
Step 1: Declare a Executer service
private ExecutorService mExecuterService = null;
Step 2:Declare a class for your list iteration and view update
class ListViewUpdater implements Runnable{
public ListViewUpdater(/* if you need you can pass list params here */){
}
#Override
public void run() {
for(int i = 0; i < searches.size(); i++) {
//Get the book
Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));
//Assign data to the adapter variables
Bitmap cover = book.getCover();
String title = book.getTitle();
String author = book.getAuthor();
}
//below code is important for Updating UI ,you should run UI Updates in UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
bookAdapter.notifyDataSetChanged();
}
});
}
}
Step 3: Initilize and call below methods
//Add data to the adapter and set the list
SearchBookDataProvider dataProvider = new SearchBookDataProvider(cover, title, author);
bookAdapter.add(dataProvider);
mExecuterService = Executors.newSingleThreadExecutor()
mExecuterService.execute(new ListViewUpdater());
It may solve your problems.
I think if you are open to use a open source project ,then my suggestion will be use RX-JAVA.Which is based in reactive and push based model.
link for rx-java.
rx-java example.
You can get the list of the books in a Thread and send a Broadcast with the data received.
Register a broadcast receiver in your MainActivity class and update the Adapter in the receiver. That should not freeze the UI.
EDIT -
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Book book = (Book)intent.getSerializableExtra("Book");
SearchBookDataProvider dataProvider = new SearchBookDataProvider(cover, title, author);
bookAdapter.add(dataProvider);
bookAdapter.notifyDataSetChanged();
}
};
Thread thread = new Thread(){
#Override
public void run()
{
for(int i = 0; i < searches.size(); i++) {
//Get the book
Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));
Intent intent = new Intent();
intent.setAction("Book Received");
intent.putExtra("Book",book);
sendBroadcast(intent);
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(bookAdapter);
registerReceiver(broadcastReceiver,new IntentFilter("Book Received"));
thread.start();
}
this is my first post here so be gentle :p
Here is the thing, I'm facing a really though issue and after several research i did not manage to figure out a clean solution. Let me explain:
I'm actually developing an android app for restaurant management.
In activity A, i'm able to create some articles with different parameters (picture, name, price ..).
I can also create a menu in which i indicate which articles are included. To do so i run Activity B that contains a dynamic list of the available articles (the ones i created) to be chosen. After picking up some of them the customised chosen objects are sent to Activity A through Parcel. And the chosen article list is updated in the menu.
But here is the thing, as far as i know, using Parcels create another instance of the object. As a result, if i modify or delete an article, the article list included in the menu does not change, and obviously i would like the list in the menu to be automatically updated.
Is there a way to simply pass customised objects through activities by reference?
What could be a clean solution to make the article list in the menu dynamic?
Here is some code:
In Activity A, in the menu interface i click + button to add an article, which run Activity B (the extras is the list of articles already included in the menu before, so in the beginning it's empty).
//Add article
FloatingActionButton addArticleButton = (FloatingActionButton)parentActivity.findViewById(R.id.addArticleButton);
addArticleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showMenuDetails(menuListView,menuAdapter,currentMenu);
parentActivity.startActivityForResult(new Intent(parentActivity.getApplicationContext(),ChooseArticleActivity.class).putParcelableArrayListExtra("menuArticleList",currentMenu.getArticles()),PICK_ARTICLES);
}
});
In activity B: I select Articles in a list of available Articles (the ones i created). After picking up i press OK button to put the list of chosen articles in result Intent as Parcelable Extras
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.choose_article_layout);
initializeLists();
this.resultIntent = new Intent();
}
private void initializeLists(){
final ListView articleToChoose = (ListView)findViewById(R.id.articleToChoose);
final ListView articleChosen = (ListView)findViewById(R.id.articleChosen);
final ArrayList<Article> articleToChooseList = (ArrayList<Article>)MainActivity.model.getArticleList().getArticleList().clone();
final ArrayList<Parcelable> articleChosenListParcelable = (ArrayList<Parcelable>)this.getIntent().getParcelableArrayListExtra("menuArticleList");
final ArticleAdapter articleToChooseAdapter = new ArticleAdapter(getApplicationContext(), articleToChooseList);
articleToChoose.setAdapter(articleToChooseAdapter);
ArrayList<Article> articleChosenListTemp = new ArrayList<>();
ArrayList<Article> articleToRemove = new ArrayList<>();
for(Parcelable a:articleChosenListParcelable){
articleChosenListTemp.add((Article)a);
for(Article article:articleToChooseList){
if(article.getName().equals(((Article) a).getName())){
articleToRemove.add(article);
}
}
}
articleToChooseList.removeAll(articleToRemove);
articleToChooseAdapter.notifyDataSetChanged();
final ArrayList<Article> articleChosenList = articleChosenListTemp;
final ArticleAdapter articleChosenAdapter = new ArticleAdapter(getApplicationContext(),articleChosenList);
articleChosen.setAdapter(articleChosenAdapter);
articleChosen.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Article articleClicked = articleChosenAdapter.getItem(position);
articleChosenList.remove(articleClicked);
articleToChooseList.add(articleClicked);
articleChosenAdapter.notifyDataSetChanged();
articleToChooseAdapter.notifyDataSetChanged();
}
});
articleToChoose.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Article articleClicked = articleToChooseAdapter.getItem(position);
if(!articleChosenList.contains(articleClicked)){
articleChosenList.add(articleClicked);
articleToChooseList.remove(articleClicked);
articleToChooseAdapter.notifyDataSetChanged();
articleChosenAdapter.notifyDataSetChanged();
}
}
});
Button okButton = (Button)findViewById(R.id.okButton);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
chosenArticleListAttr = articleChosenList;
resultIntent.putParcelableArrayListExtra("articleList",chosenArticleListAttr);
setResult(RESULT_OK,resultIntent);
finish();
}
});
Button cancelButton = (Button)findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
In activity A, in onActivityResult i catch the result and update the list, but the added Articles here are not the same instance as the article list in the model
if(requestCode==PICK_ARTICLES && resultCode==RESULT_OK){
ArticleAdapter articleAdapter = (ArticleAdapter) gestionMenusLayout.getMenuArticleListView().getAdapter();
ArrayList<Parcelable> chosenArticleList = (ArrayList<Parcelable>)data.getParcelableArrayListExtra("articleList");
gestionMenusLayout.getCurrentMenu().getArticles().clear();
for(Parcelable a:chosenArticleList){
gestionMenusLayout.getCurrentMenu().addArticle((Article)a);
}
articleAdapter.notifyDataSetChanged();
}
For debugging purpose only, I suggest that you use a public static List<Article> articleList and call it directly from whether activity A or B
A better but take-alittle-more-effort solution is that you store the list in a database, and every updates, queries, ... come through it.You can use the server's database (where people usually get articles from), or a offline database like Realm here
I figured it out with a quite easy and simple solution finally.
I keep passing my Article objects through intents by parcels.
But as it creates a new instance, instead of adding this instance i add the original one (the one from the model) after an equality key check (the name of the article). By doing so i keep the reference on my Article.
Thank you for helping!
Edit:
Here is the code:
if(requestCode==PICK_ARTICLES && resultCode==RESULT_OK){
ArticleAdapter articleAdapter = (ArticleAdapter) gestionMenusLayout.getMenuArticleListView().getAdapter();
ArrayList<Parcelable> chosenArticleList = (ArrayList<Parcelable>)data.getParcelableArrayListExtra("articleList");
gestionMenusLayout.getCurrentMenu().getArticles().clear();
ArrayList<Article> modelArticles = MainActivity.model.getArticleList().getArticleList();
for(Parcelable a:chosenArticleList){
for(Article modelArticle:modelArticles){
if(((Article)a).getName().equals(modelArticle.getName())){
gestionMenusLayout.getCurrentMenu().addArticle(modelArticle);
}
}
}
articleAdapter.notifyDataSetChanged();
}
I'm an Android newbie developer and having an issue with a tiny Android app I'm developing which I suspect is related to timing of dynamic view creation. It's a little scorekeeper app and it has dynamically generated player buttons and text fields, defined in a Player class. Here's an excerpt of how I'm doing this:
public Player(String name, int score, int number, boolean enabled, RelativeLayout mainScreen, List<Button> presetButtonList, Editor editor, Context context) {
super();
this.name = name;
this.score = score;
this.number = number;
this.enabled = enabled;
this.editor = editor;
// Get the lowest child on the mainScreen
Integer count = mainScreen.getChildCount(), lowestChildId = null;
Float lowestChildBottom = null;
for (int i = 0; i < count; i++) {
View child = mainScreen.getChildAt(i);
if ((lowestChildId == null || child.getY() > lowestChildBottom) &&
!presetButtonList.contains(child)) {
lowestChildId = child.getId();
lowestChildBottom = child.getY();
}
}
playerNameText = (EditText) setTextViewDefaults(new EditText(context), name);
playerNameText.setSingleLine();
// playerNameText.setMaxWidth(mainScreen.getWidth());
// playerNameText.setEllipsize(TextUtils.TruncateAt.END); //TODO: Prevent names which are too long for screen
playerNameText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable changedText) {
setName(changedText.toString());
updateScreen();
}
public void beforeTextChanged(CharSequence changedText, int start, int count, int after) {}
public void onTextChanged(CharSequence changedText, int start, int before, int count) {}
});
RLParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (lowestChildId != null) {
RLParams.addRule(RelativeLayout.BELOW, lowestChildId);
} else {
RLParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
RLParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
}
RLParams.setMargins(0, 10, 0, 10);
mainScreen.addView(playerNameText, RLParams);
the class further defines buttons and etc in a similar fashion, aligning tops with the name text view. I call this when a user clicks a button to add a player, and it works fine, displaying each player below the first on down the screen. The problem comes in when I'm loading a bunch of saved players at the start. Here's where i load the players:
public void loadData() {
RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
playerCount = savedData.getInt("playerCount", playerCount);
Player player;
String name;
playerList.clear();
for (int i=1; i<=playerCount; i++) {
name = savedData.getString("name" + i, null);
if (name != null) {
Log.v("name", name);
player = new Player(name, savedData.getInt("score" + i, 0), i, savedData.getBoolean("enabled" + i, false), mainScreen, presetButtonList, editor, this);
playerList.add(player);
player.updateScreen();
}
}
updateScreen();
}
Finally, I call the loadData() method when the app starts, here:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
savedData = this.getPreferences(Context.MODE_PRIVATE);
editor = savedData.edit();
presetButtonList.add((Button)findViewById(R.id.newGame));
presetButtonList.add((Button)findViewById(R.id.addPlayer));
presetButtonList.add((Button)findViewById(R.id.removePlayer));
loadData();
}
The result? When there are more than two players to load, all the players get loaded to the same spot, on top of Player 2.
I suspect somehow that the players are all being generated at the same time and thus all believing that the lowest player view is Player 1, and not checking each other. I've tried triggering the load later than onCreate() and it still happens. I also tried adding a 3 second sleep within the for loop of loadData() after each player loads to see if that helped, but no luck.
Am I making bad assumptions? What am I doing wrong and how might I fix it?
I suspect what is happening here is that you are attempting to position views that don't have IDs (it looks like you don't set them anywhere in your code). Dynamically created views don't automatically have IDs, so a call to getId() will return NO_ID (See documentation). If you want to use an ID you will have to set it yourself using View.setId().
It was a timing issue after all. I needed to wait for the main screen to load before I could add views to it. Unfortunately, it would never load until all activity on the UI thread was finished.
Thus, I needed threading. I ended up putting loadData() in a thread, like this:
new Thread(new loadDataAsync(this)).start();
class loadDataAsync implements Runnable {
MainActivity mainActivity;
public loadDataAsync(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
#Override
public void run() {
try {
Thread.sleep(700);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
loadData(mainActivity);
}
}
Then I created the players back on the UI thread after the initial sleep to give time for the UI to load.
runOnUiThread(new Runnable() {
Player player;
RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
#Override
public void run() {
player = new Player(savedData.getString("name" + playerNum, null), savedData.getInt("score" + playerNum, 0), playerNum, savedData.getBoolean("enabled" + playerNum, false), mainScreen, presetButtonList, editor, mainActivity);
playerList.add(player);
player.updateScreen();
mainScreen.invalidate();
}
});
Not the most elegant solution, but it works for now.
The title says it all, I'm trying to do that because I obtain a list from parse and the user must choose one of them from a spinner and based on the user's choice it responds and sets another filter to another spinner. The problem I'm having (really not much of a deal, but it's something that I'd like to do) is that when the list gets obtained from Parse it automatically selects the first one it retrieves and fills all the spinners automatically (of course you can change it and it will work perfectly).
The question is, how do I retrieve a list from parse, add it into a spinner in a way that it doesn't fill everything by itself ?
Here's my piece of code where I obtain the list and add it into a spinner:
groupSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
System.out.println("Group Item Selected Ran");
final String spinI1 = groupSpinner.getSelectedItem().toString();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Hospitales");
query.whereEqualTo("grupo", spinI1);
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> parseObjects, ParseException e) {
int size = 0;
size = parseObjects.size();
String[] mod = new String[size];
for (int i = 0; i < parseObjects.size(); i++) {
mod[i] = parseObjects.get(i).getString("Hospital");
System.out.println(mod[i]);
}
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(HandsetLocation.this, android.R.layout.simple_spinner_item, mod);
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // The drop down view
hospitalSpinner.setAdapter(spinnerArrayAdapter);
}
});
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Any help would be appreciated greatly!
At my phone so cannot properly indent the code but here it goes:
String[] mod = new String[size+1];
mod[0] = "select value";
for (int i = 0; i < parseObjects.size(); i++) {
mod[i+1] = parseObjects.get(i).getString("Hospital");
System.out.println(mod[i+1]);
}