Custom ListView not getting updated - android

I'm developing a currency exchange app and I'm having some problems with updating my ListView after extracting the rates from an API.
Ignore the flags, I just put whatever files I had to test the solution
On the start of my activity, I am defining:
final ArrayList<ItemData> list = new ArrayList<ItemData>();
final String[] web = {
"EUR", "JPY", "USD", "GBP"
};
final Integer[] imageId = {R.drawable.austria, R.drawable.bangladesh, R.drawable.benin, R.drawable.uk};
private static String _spinnerData;
public static String test;
public static synchronized String getCurrentSpinner(){
if (_spinnerData == null) {
String _spinnerData;
}
return _spinnerData;
}
And onCreate() is defined as:
... not important ...
Spinner spin = (Spinner) findViewById(R.id.spinner_complist);
final SpinnerAdapter adapter1 = new SpinnerAdapter(this,
R.layout.spinner_layout, R.id.txt, list);
spin.setAdapter(adapter1);
spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
ItemData item = (ItemData) (parentView.getItemAtPosition(position));
Log.i("item_1", item.getText());
String spinnerData = getCurrentSpinner();
spinnerData = item.getText();
}
I then have a custom Adapter to put the flags+name, where the name is a textview.
Afterwards, I get my conversion rate from an API, through a function getRate() that is working.
On the custom adapter, I have overriden the getView method:
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.mylist, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.itemName);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
imageView.setImageResource(imageId[position]);
String currency;
txtTitle.setText(web[position]);
String spinnerData= getCurrentSpinner();
if (spinnerData!=null) {
currency=spinnerData;
getRate(currency, web[position], txtTitle);
}
return rowView;
}
So, in getRate I obtain a String from each row of the ListView and replace it by the value in another coin.
My problem is: If I write getRate("EUR",web[position],txtTitle), everything works as intended.
However, if I put the code as it is, it just doesn't update my ListView. I put a breakpoint and currency is "EUR", so it should be equivalent to what I had by hardcoding the string.
I think that probably the ListView isn't getting properly updated, or the function is making some callback that is replacing my TextViews with the original values.
Any ideas?
Thanks in advance,

Two things stand out to me.
First, this block:
public static synchronized String getCurrentSpinner(){
if (_spinnerData == null) {
String _spinnerData;
}
return _spinnerData;
}
This doesn't really make sense. It reads "if the static scoped _spinnerData is null, create another locally scoped String also called _spinnerData and do nothing with it, then return the statically scoped instance."
And second, this logic:
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
ItemData item = (ItemData) (parentView.getItemAtPosition(position));
Log.i("item_1", item.getText());
String spinnerData = getCurrentSpinner();
spinnerData = item.getText();
}
This reads "create a temporary string called spinnerData that is initialized with the return value of getCurrentSpinner() then immediately replace it with the value of item.getText() then throw the whole thing away (because it's never used thereafter)".
It appears to me you have a misunderstanding in how references work. I think what you are trying to do is save the current spinner selection and use that in your getView().
If that's the case, you would do something like this:
private String _spinnerData; // Does not need to be static
// In onItemSelected
ItemData item = (ItemData) (parentView.getItemAtPosition(position));
Log.i("item_1", item.getText());
_spinnerData = item.getText(); // Save the last item selected
// In getView()
// Call this method with the last known spinner selection
getRate(_spinnerData, web[position], txtTitle);
I would have to assume you are new to Java and don't fully understand how references and scope work. Is that a fair assumption? If so, I strongly suggest you take a step back from Android and work on getting more familiar and comfortable with Java before proceeding. Android is complicated enough without having to figure out the language as you go as well.
Hope that helps!

I think you have some problems with the flow of the data in your Activity.
The getView in the listview should return a view with the populated data from a data source that has the data.
I would advice changing to have something like:
Snippet position selected -> call web API to get any data that you need -> when is returned add it to a list of data that is being displayed on the listview -> then call in the adapter of the listview notifyDataSetChanged()
I would recommend this article for more information about using listviews: http://www.vogella.com/tutorials/AndroidListView/article.html

Related

Android programming: I cant get data to reload into arrayadapter

I am still stuck with this issue, can anyone help. It seems that my problem is that I cant update the data list. I have tried every solution that I've searched for on google etc.. but half the time i'm not even sure that I'm doing the correct thing.
I've used the onResume() to call notifyDataSetChanged, it didn't work. I've tried putting a refresh method into the adapter which i then called in OnResume(). Again it didn't work. Some people suggest clearing the adpater (adapter.clear();) in onResume and then using the addAll() function to relist the data but nothing works.
There has to be a simple solution to this. I have literally been stuck on this for 2 days now. very frustrated.
Here's my Fragment code again...
enter code here
public class SavedAppFragment extends ListFragment {
private static final String TAG = "AppClicked"; //DEBUGGER
private ArrayList<App> mSavedApps;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Populate the ArrayList
mSavedApps = SavedAppData.get(getActivity()).getApps();
AppAdapter adapter = new AppAdapter(mSavedApps);
setListAdapter(adapter);
}
//LIST ITEM CLICKED: /*Control what happens when list item is clicked: I.E. Load up a quiz while putting an EXTRA key containg the package name of the App to be launhced should the user get the question correct */ #Override public void onListItemClick(ListView l, View v, int position,long id) { //Return the crime for the list item that was clicked App c = ((AppAdapter) getListAdapter()).getItem(position); Log.d(TAG, "was clicked");
//Start the Activity that will list the detail of the app
Intent i = new Intent(getActivity(), Quiz_Activity.class);
String name = c.getPackage();
i.putExtra("packagename", name);
startActivity(i);
}
private class AppAdapter extends ArrayAdapter {
private ArrayList<App> mSavedApps;
public AppAdapter(ArrayList<App> apps) {
super(getActivity(), 0, apps);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//If we weren't given a view, inflate one
if (null == convertView) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_app, null);
//((AppAdapter) getListAdapter()).notifyDataSetChanged();
}
((AppAdapter) getListAdapter()).notifyDataSetChanged();
//Configure the view for this crime
App c = getItem(position);
TextView nameTextView = (TextView) convertView.findViewById(R.id.app_name);
nameTextView.setText(c.getName());
// nameTextView.setText(applicationInfo.loadLabel(packageManager));
TextView packageTextView = (TextView) convertView.findViewById(R.id.app_package);
packageTextView.setText(c.getPackage());
CheckBox appCheckBox = (CheckBox) convertView.findViewById(R.id.app_checked);
appCheckBox.setChecked(c.isChecked());
//Return the view object to the ListView
return convertView;
}
}
}
THANKS!!!
When you return to Activity B, the previous Activity B hasn't been destroyed. Thus, it skips the onCreate. Move all of the stuff you want to make sure happens every time into the onResume. I think you want to make your Adapter a class variable (I'll call it mAdapter) in onCreate, and add code that will get data from the list directly. If you need to do something, put a "refresh" function in the adapter. I'm assuming you have a custom Adapter, because I've never heard of AppAdapter. If you don't, then extend AppAdapter and add that functionality. Thus, your onCreate should look like this:
mAdapter = new AppAdapter(mSavedApps);
setListAdapter(mAdapter);
Your onRefresh could update the data contained in the adapter by some new update function, like so:
mAdapter.update(SavedAppData.get(getActivity()).getApps());

AsyncTask with ViewHolder pattern doesn't work

I'm trying to optimize my code into my adapter with AsyncTask to do a internet request to read a JSON and display its data.
My code before the change with AsyncTask works perfectly so i'm doing something wrong now because it isn't setting the text after the request is expired. I want that while i scroll the listview, AsyncTask run the code of the internet connection and after it's done, it will change the text into textviews from default to right one.
Adapter class
public class ListBookmarksAdapter extends ArrayAdapter<BookmarksHandler>{
private final Context context;
private List<BookmarksHandler> list;
DatabaseHandler dh;
SQLiteDatabase db;
ViewHolder viewHolder;
Gson gson;
public ListBookmarksAdapter(Context context, List<BookmarksHandler> list) {
super(context, R.layout.listbookmarks, list);
this.context = context;
this.list = list;
}
static class ViewHolder{
TextView tvTitle;
TextView tvChapter;
ImageView immagine;
}
#Override
public View getView(final int position, View rowView, ViewGroup parent) {
gson = new Gson();
dh = new DatabaseHandler(context);
db = dh.getWritableDatabase();
if(rowView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.listbookmarks, parent, false);
viewHolder = new ViewHolder();
viewHolder.tvTitle = (TextView) rowView.findViewById(R.id.tvTitle);
viewHolder.tvChapter = (TextView) rowView.findViewById(R.id.tvChapter);
viewHolder.immagine = (ImageView) rowView.findViewById(R.id.imageView);
rowView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) rowView.getTag();
}
new AsyncList(position).execute("http://www.myurl.com/" +list.get(position).getId_manga() + "/");
return rowView;
}
private class AsyncList extends AsyncTask<String, Void, String> {
int position;
public AsyncList(int position){
this.position = position;
}
#Override
protected String doInBackground(String... params) {
String urlManga = null;
try {
urlManga = MainActivity.connessione(params[0]);
} catch (Exception e) {
e.printStackTrace();
}
assert urlManga != null;
return urlManga.trim();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
MangaSpec manga = gson.fromJson(result, MangaSpec.class);
viewHolder.tvTitle.setText(manga.getTitle());
viewHolder.tvTitle.setSelected(true);
if(Integer.parseInt(String.valueOf(manga.getStatus()))==2)
viewHolder.immagine.setImageResource(R.drawable.book_close);
List generic = manga.getChapters();
for(int i=0; i<generic.size(); i++){
List chapters = (List) generic.get(i);
if(((String) chapters.get(3)).equals(list.get(position).getId_chapter())){
double numero = (Double) chapters.get(0);
String titoloC = (String) chapters.get(2);
if((numero-(int)numero)!=0)
viewHolder.tvChapter.setText(numero+" - "+titoloC);
else
viewHolder.tvChapter.setText((int)numero+" - "+titoloC);
viewHolder.tvChapter.setSelected(true);
}
}
}
}
}
Here is MainActivity.connessione method:
public static String connessione(String url) throws Exception {
URL website = new URL(url);
URLConnection connection = website.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
response.append(inputLine);
in.close();
return response.toString();
}
And here is a screen of what i mean:
"Shingeki no Kyoijin" and "63 - Catene" are the items on the first row (follow the arrows). The others two items in the list have different values. As you see, the text is set as default one (Text) for the first two items and it's set wrong for the last one.
A ViewHolder is specific to an item not the whole adapter, so move the ViewHolder variable declaration inside the getItem method. Now you see the problem: the AsyncTask does not see any ViewHolders.
Instead of int position (which you don't use) let the async task constructor take a ViewHolder parameter. Furthermore declare your custom async task as static like so:
private static class AsyncList extends AsyncTask<String, Void, String> {
By doing this you ensure that you cannot access anything you don't need to / should not have access to from inside the async task.
Suggestion: Move the JSON parsing to background (and change the async task result type to MangaSpec).
Your biggest problem is that you have declared a single ViewHolder to handle all the views in your adapter.
So here's how the problem happens:
ListView calls getView() in your adapter for the first item. Since there are no views to recycle, you inflate a view, create a ViewHolder, and start a download. ListView draws the first item using the values from your inflated layout.
ListView calls getView() two more times to draw the other items while the download is still in progress. Since there's only one viewHolder for the entire adapter, each time you say viewHolder = new ViewHolder() you are replacing the ViewHolder created by the previous item.
The download for the first item completes. But since you overwrote the ViewHolder, the data for the download of the first position is being written into the views for the ViewHolder of the third position. Once the other downloads complete, they are also being written into this same ViewHolder.
I would imagine that if you scroll this list up and down, you will see items changing pretty randomly as you scroll your list.
Now, even if you do fix your code to have an individual ViewHolder for each view, you will still have problems because view recycling will cause your downloaded data to draw in the wrong place when a view is recycled between the download start and the download end.
In addition, you have set up a situation where the same server data will be downloaded over and over as the user scrolls up and down, and that is not efficient.
Here is what I think you should do:
If your list item has a title, a chapter, and an image, then you should create a model class that has a String property for the title, a String property for the chapter, and a String property for the image name or image URL. Let's call this class Bookmark.
Because Android UI uses the Model/View/Controller pattern, what that means is that whatever is in the adapter list should be the actual data that is displayed. It looks like you are passing the array of bookmark ids that are not what is displayed in the list item.
Create an ArrayList<Bookmark>. Then for each BookmarksHandler in your list, create a blank Bookmark object, add it to the list then hand this list to the ArrayAdapter. This means you have a list of blank items to start.
Your getView() method will simply pull whatever data is in Bookmark list position n to create the view for item position n. If you use a ViewHolder in getView(), make sure you create a new ViewHolder that is not shared with other items.
Start your data download. It looks like your REST interface can only get one bookmark at a time. If there is a way you could change it so you could post all the bookmark ids in the list and get one big JSON array back with all your bookmark data, that would be more efficient.
When your data download completes, you would loop through your JSON data and update each blank Bookmark item in the adapter's ArrayList, then call notifyDataSetChanged() on the adapter. This tells the ListView that its backing data has changed and it's time to update the ListView on the screen.
The biggest thing to know here is that the downloaded data should go into the adapter data so your getView() can create a list item from it. Going directly to the view from a download is only for the actual image.
The image download is not a trivial task. For that I refer you to this excellent article on the Android Developer's blog which explains it way better than I can.
I hope this has been helpful; I know it's a lot to digest. For further information, look for more tutorials online on how to update ListViews with downloaded data.

How to do put a CheckBox in a ListView?

I have a listview with a custon adapter. I the row's layout, I have a text and a checkbox.
When I load the listview, I get the data from a database and it has one colunm that determine if the row is cheched or not. When I load the list, its ok, the rows that has to stay checked, stays checkd, and the others no. The problem is: when I unckheck a row ans roll the list down and up, when I return to the start, the row that I had unchecked, returns checked again, how can I resold this problem:
The getView() code below:
public View getView(int index, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.linha_acessorios, parent, false);
}
final AcessoriosItensLista acessorios = (AcessoriosItensLista)getItem(index);
final ImageView imgAcessorio = (ImageView)view.findViewById(R.id.imgAcessorioLista);
final CheckBox cb = (CheckBox)view.findViewById(R.id.cbListaAcessorios);
TextView tvNome = (TextView) view.findViewById(R.id.tvNomeAcessoriosLinha);
tvNome.setText(acessorios.getNomeAcessorio());
final Integer iditem = Integer.valueOf(acessorios.getId());
boolean ch = acessorios.isChecked();
final Integer position = Integer.valueOf(index);
if(ch){
if(!checked.contains(iditem)){
checkedPositions.add(position);
checked.add(iditem);
}
}
cb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(checked.contains(iditem)){
checked.remove(iditem);
checkedPositions.remove(position);
}
if (((CheckBox) v).isChecked()) {
checkedPositions.add(position);
checked.add(iditem);
int id = context.getResources().getIdentifier("acc_gold_"+acessorios.getId(), "drawable", context.getPackageName());
imgAcessorio.setBackgroundResource(id);
}
else if(checkedPositions.contains(position)) {
checkedPositions.remove(position);
checked.remove(iditem);
int id = context.getResources().getIdentifier("acc_"+acessorios.getId(), "drawable", context.getPackageName());
imgAcessorio.setBackgroundResource(id);
}
}
});
if(checkedPositions.contains(position)){
cb.setChecked(true);
int id = context.getResources().getIdentifier("acc_gold_"+acessorios.getId(), "drawable", context.getPackageName());
imgAcessorio.setBackgroundResource(id);
} else {
cb.setChecked(false);
int id = context.getResources().getIdentifier("acc_"+acessorios.getId(), "drawable", context.getPackageName());
imgAcessorio.setBackgroundResource(id);
}
return view;
}
My guess is that probably you're unchecking that CheckBox but you're not saving its status anywhere, so when that row disappears from the screen by scrolling and you scroll down again, it loads the data again from the database and it's checked in it. I don't know how you're handling your ArrayAdapter extension, but I recommend saving the constructor's ArrayList as an instance inside the class, updating that value inside of it on uncheck, and call notifyDataSetChanged().
---- EDIT ----
To store the ArrayList inside your class, you'll have to create a separate class (with the two fields you're working on), for example:
class MyRow {
CheckBox cb;
TextView tv;
}
So when you declare your custom adapter in your Activity, you'll have to declare previously an ArrayList with some initial elements (or even empty):
ArrayList<MyRow> myList = new ArrayList<MyRow>();
MyRow row1 = new MyRow();
row1.cb.isChecked(...);
row1.tv.setText(...);
myList.add(row1);
Then you call the constructor of your adapter class, something like this:
MyArrayAdapter adapter = new MyArrayAdapter(context, R.layout.your_layout, myList);
So when you pass it to the constructor of your adapter class, you save a copy of it in that class:
public class MyArrayAdapter extends ArrayAdapter {
final private ArrayList<MyRow> myContent;
...
MyArrayAdapter(Context context, int my_layout, ArrayList<MyRow> myContent_) {
...
myContent = myContent_
}
}
So now, any content you change (like for example checking/unchecking a checkbox) you have to save its state in the myContent array. You would find that item by getItem(position) in your getView() method and make the changes you need. After it, you just have to call the notifyDataSetChanged(); method and it will automatically display the changes in your ListView.
It's almost as it your list items are being re-redered or recreated when they go off screen, now the easiest and obvious solution here is to trigger an event when your checkbox is clicked so make an onclick event in your adapter that is triggered when the checkbox is checked or unchecked and updates the data source.

How to get Spinner inside ListView work in Android?

I am developing an app in which I need a ListView whose rows have a TextView, 2 CheckBox and a Spinner.
However, I am experiencing issues with onItemSelected() of the Spinner, as it gets called each time it is displayed for each row. In this method I am updating database records with the selected option, but as Android calls it automatically, every time the items get reset because Android calls it with position 0 and this is the value updated in the database.
I have read a lot of links about the issue with onItemSelected() and some hacks, but all of them are to use without a ListView. Any points here?
I have tried to track in a List which positions are actually displayed to make it work but it does not. I think it is because of the recycling in Android that causes the troubleshooting method get called for Spinners already shown!
So the point is: How can I differenciate a real call to onItemSelected() because of a user selection from the Android call when displaying the Spinner?
Here is the code of my adapter that extends SimpleCursorAdapter.
Thank you so much in advance.
public ParticipationAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
mActivity = (Activity)context;
ParticipationComment.ParticipationCommentManager commentManager = new ParticipationComment.ParticipationCommentManager(mActivity);
mParticipationCommentsCursor = commentManager.get();
mActivity.startManagingCursor(mParticipationCommentsCursor);
commentManager.detach();
mPositionsOfCursorIds = getPositionsOfCursorIds(mParticipationCommentsCursor);
mSpinnerPositionsDisplayed = new ArrayList<Integer>();
}
#Override
public View getView(final int participationPosition, View convertView, ViewGroup parent) {
final Cursor participationsCursor = getCursor();
mActivity.startManagingCursor(participationsCursor);
participationsCursor.moveToPosition(participationPosition);
View participationRow;
if (convertView == null) {
participationRow = LayoutInflater.from(mActivity).inflate(R.layout.participation_row_student, null);
} else {
mSpinnerPositionsDisplayed.remove((Integer)convertView.getTag());
participationRow = convertView;
}
participationRow.setTag(participationPosition);
Spinner commentSpinner = (Spinner)participationRow.findViewById(R.id.participation_comment_id_spinner);
SimpleCursorAdapter commentSpinnerAdapter = new SimpleCursorAdapter(
mActivity,
android.R.layout.simple_spinner_item,
mParticipationCommentsCursor,
new String[] {DatabaseManager.NAME},
new int[] {android.R.id.text1}
);
commentSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
commentSpinner.setAdapter(commentSpinnerAdapter);
long participationCommentId = participationsCursor.getLong(participationsCursor.getColumnIndex(DatabaseManager.PARTICIPATION_COMMENT_ID));
if (participationCommentId != 0) {
commentSpinner.setSelection(mPositionsOfCursorIds.get(participationCommentId));
}
commentSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
participationsCursor.moveToPosition(participationPosition);
if (!mSpinnerPositionsDisplayed.contains(participationPosition)) {
// Android calls this method the first time a Spinner is displayed,
// to differentiate from a real user click we check if the current Spinner's position
// in the ListView is being shown
mSpinnerPositionsDisplayed.add(participationPosition);
} else {
ParticipationComment participationComment = new ParticipationComment((Cursor)parent.getItemAtPosition(position));
Participation.ParticipationManager participationManager = new Participation.ParticipationManager(mActivity);
Participation participation = new Participation(participationsCursor);
participation.setConnectionProfileParticipationCommentId(participationComment.getConnectionProfileId());
participation.setParticipationCommentId(participationComment.getIdOpenErp());
participation.setChanged(true);
participationManager.update(participation);
participationManager.detach();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Not used
}
});
TextView studentName = (TextView)participationRow.findViewById(R.id.participation_student_name);
studentName.setText(participationsCursor.getString(participationsCursor.getColumnIndex(DatabaseManager.NAME)));
CheckBox expectedPresent = (CheckBox)participationRow.findViewById(R.id.participation_expected_present_value);
expectedPresent.setChecked(participationsCursor.getInt(participationsCursor.getColumnIndex(DatabaseManager.EXPECTED_PRESENT)) == 1);
CheckBox present = (CheckBox)participationRow.findViewById(R.id.participation_present_value);
present.setChecked(participationsCursor.getInt(participationsCursor.getColumnIndex(DatabaseManager.PRESENT)) == 1);
return participationRow;
}
A better way is to use a AlertDialog Variant.. like this.. and create a button which initially has the first selection as its Text and its changed based on the AlertDialog choice..
What about using a small flag to discard first call of ItemSelected ?

Setting ID for Spinner items

I have an array of Strings I'm populating a Spinner object with. However, I'd like to attach an ID to each element of the Spinner, so when the user selects an item, I have its ID to use to save to some other piece of data. How can I do this?
Create a class StringWithTag and use in place of the string name in the list like so :-
public class StringWithTag {
public String string;
public Object tag;
public StringWithTag(String stringPart, Object tagPart) {
string = stringPart;
tag = tagPart;
}
#Override
public String toString() {
return string;
}
}
in the add items to spinner part :-
List<StringWithTag> list = new ArrayList<StringWithTag>();
list.add(new StringWithTag("Oldman", "12345"));
list.add(new StringWithTag("Umpire", "987654"));
list.add(new StringWithTag("Squad", "ABCDEE"));
ArrayAdapter<StringWithTag> adap = new ArrayAdapter<StringWithTag> (this, android.R.layout.simple_spinner_item, list);
....
....
in the listener :-
public void onItemSelected(AdapterView<?> parant, View v, int pos, long id) {
StringWithTag s = (StringWithTag) parant.getItemAtPosition(pos);
Object tag = s.tag;
}
voila!
}
What do you mean by id. You can use ArrayAdapter to populate the Spinner. When item is selected just get the element from the adapter and save the data you want.
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<MyObject> adapter = ... // initialize the adapter
adapter.setDropDownViewResource(android.R.layout.some_view);
spinner.setAdapter(adapter);
and when item is selected
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
MyObject selected = parent.getItemAtPosition(pos);
// save any data relevant with selected item
}
If you are storing your data in db you can use CursorAdapter and in onItemSelected to fetch the selected item id from the cursor.
I don't think you can attach an arbitrary ID to elements of a text array resource, if that's what you're using.
I think the simplest way to attach such an ID would be to either hard-code (if you're using a static text resource) or dynamically build (if you get the strings at runtime) a mapping from (String position in array)->(primary key).
EDIT: On the other hand, Mojo Risin has a point - you should check to see if the CursorAdapter API already does what you need for you.
Andrew Hi, it's been a long time but it's worth to write.
You can set a tag for each row when you'r inflating spinnerLayout in SpinnerAdapter:
spinnerView = inflater.inflate(spinnerLayout, parent, false);
spinnerView.setTag("Your Tag");
And then you can get the tag with:
yourSpinner.getSelectedView().getTag();
I think The best solution is to add one more spinner and fill it with the ids but make the visibility of it to gone

Categories

Resources