Currently I am able to populate my spinner two ways one way gives me results from the database which is what I need but the text in the spinner is in JSON format, it all works but it looks bad, then if I extract the name from the JSON and use it I lose the value part of the name value pair.
I’ve been informed that I need to use a BaseAdapter subclass to be able to do what I need to do. The code below works just like I would love it to but the data is hard coded in, which is no use.
What I want to do is fill MyData below with the JSON data returned from the database.
This code:
final MyData items[] = new MyData[4];
items[0] = new MyData( "Ken's Plimbing","125738468");
items[1] = new MyData( "Peninsula Pests","3787906453");
items[2] = new MyData( "Joe's Electrical","129754354");
items[3] = new MyData( "Garderning Supplies","097803452");*/
ArrayAdapter<MyData> adapter = new ArrayAdapter<MyData>(PropertyManagement.this, android.R.layout.simple_spinner_item, items );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
userSpinner.setAdapter(adapter);
userSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
MyData d = items[position];
Toast.makeText(PropertyManagement.this, d.getValue(), Toast.LENGTH_SHORT).show();
}
public void onNothingSelected(AdapterView<?> parent) {
}
}
);
With this BaseAdapter:
class MyData {
public MyData( String spinnerText, String value ) {
this.spinnerText = spinnerText;
this.value = value;
}
public String getSpinnerText() {
return spinnerText;
}
public String getValue() {
return value;
}
public String toString() {
return spinnerText;
}
String spinnerText;
String value;
Works!
But I need to fill MyData with the JSON array returned from the database. I have been doing that with the following as per the first paragraph in this post.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(PropertyManagement.this, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
final MyData items[] = new MyData[4];
for (int i = 0; i < myUsers.length(); ++i)
{
adapter.add(myUsers.getJSONObject(i).getString("BusinessName"));
};
userSpinner.setAdapter(adapter);
The JSONArray/string looks like this,
{"BusinessName":"Petes Plumbing","BusinessPhone":"0434943743"},{"BusinessName":"Joes Electrical","BusinessPhone":"0466367279"}
Any help would be greatly appreciated.
Cheers,
Mike.
You are super close here, instead of adapter.add in your for loop you need to add it to items. Refactor like this:
final MyData items[] = new MyData[myUsers.length()];
for (int i = 0; i < MyData.length(); ++i){
items[i] = new MyData(myUsers.getJSONObject(i).getString("BusinessName"), myUsers.getJSONObject(i).getString("BusinessPhone"));
}
ArrayAdapter<MyData> adapter = new ArrayAdapter<MyData>(PropertyManagement.this, android.R.layout.simple_spinner_item, items );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
userSpinner.setAdapter(adapter);
What is different here is your finding the length of your JSONArray, creating a new array of MyItem of that size. Then you initialize the items with new MyItems based on values from your JSONArray. Finally, you are creating the adapter with items just like you did in the first example. I'm assuming in this example that myUsers in a JSONArray.
Related
ArrayList<String> stepsList = new ArrayList<>();
ArrayList<Integer> stepsPosList = new ArrayList<>();
stepsAdapter = new ArrayAdapter<String>(this,R.layout.steps_item,R.id.etStepsDetails,stepsList);
stepsAdapter2 = new ArrayAdapter<Integer>(this,R.layout.steps_item,R.id.tvStepsPosition,stepsPosList);
stepsView.setAdapter(stepsAdapter);
stepsView2.setAdapter(stepsAdapter2);
Is it possible to combine the 2 array adapter into 1? The layout is on the same page but I need 2 id and 2 array list into each. and then call the list view.
POJO CLASS
public class CombineData {
ArrayList<String> stepsList;
ArrayList<Integer> stepsPosList;
public CombineData(ArrayList<String> stepsList,ArrayList<Integer> stepsPosList){
this.stepsList = stepsList;
this.stepsPosList = stepsPosList;
}
public CombineData(){
}
public ArrayList<String> getStepsList() {
return stepsList;
}
public void setStepsList(ArrayList<String> stepsList) {
this.stepsList = stepsList;
}
public ArrayList<Integer> getStepsPosList() {
return stepsPosList;
}
public void setStepsPosList(ArrayList<Integer> stepsPosList) {
this.stepsPosList = stepsPosList;
}
}
THIS LINE SHOWS AN ERROR : CANNOT RESOLVE CONSTRUCTOR ARRAYADAPTER... int,int,ArrayList
stepsAdapter = new ArrayAdapter<CombineData>(this,R.layout.steps_item,R.id.etStepsDetails,stepsList);
you should make POJO class
class CombineData(
ArrayList<String> stepsList,
ArrayList<Integer> stepsPosList
)
{
getter()/setter()
}
then change adapter
stepsAdapter = new ArrayAdapter<CombineData>(this,R.layout.steps_item,R.id.etStepsDetails,stepsList);
Now, you can access in the listview like this
item.stepsList
item.stepsPosList
I am currently trying to add a value to an ArrayList object from a method inside of another class.
Here is the class I have created for the ArrayList Object:
public class ArrayClass {
public static ArrayList<String> array = new ArrayList<>();
public static void add_val(String s){
array.add(s);
}
public static int get_size(){
return array.size();
}
public static String get_val(int i){
return array.get(i);
}
}
And the other class where I attempt to edit the ArrayList object:
ArrayClass fill = new ArrayClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_explore);
Response.Listener<String> responseListener4 = new Response.Listener<String>(){
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse4 = new JSONObject(response);
boolean success = jsonResponse4.getBoolean("success");
if (success){
int l;
String filled;
int length4 = jsonResponse4.length();
for (l=0;l<length4;l++){
filled = jsonResponse4.getString(l+"");
fill.add_val(filled);
}
}else{
AlertDialog.Builder builder = new AlertDialog.Builder(ExploreActivity.this);
builder.setMessage("Could not retrieve restaurant tables filled")
.setNegativeButton("Retry", null)
.create()
.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
FilledRequest filledRequest = new FilledRequest(responseListener4);
RequestQueue queue4 = Volley.newRequestQueue(ExploreActivity.this);
queue4.add(filledRequest);
If you look in the onResponse method, you can see the attempt to add a value from the jsonResponse into the ArrayClass object. However, when I launch my app, it does not add the value into the object. I'm used to python global variables and not having to deal with the semantics of java, so if you could shed some light on what changes need to be made, I would greatly appreciate it.
Apart from other given answers/solutions to the issue you are facing, let me share a best and optimized way to implement JSON parsing in Android.
I would suggest you to check GSON or Jackson libraries which provides Java serialization/deserialization that can convert Java Objects into JSON and back.
There are some benefits it does provide, one of the main benefits is you do not need to implement parsing manually and less chances of mistakes in implementing parsing, like you may make a mistake in mentioning key "Success" or "success" or any such silly mistakes!
Firstly, since your variable is static, and the methods are static too, you don't have to instantiate the object. You could do something like this:
ArrayClass.add_val("Hello");
But if you want to instantiate then you can do this:
public class ArrayClass {
private ArrayList<String> array;
public ArrayClass() {
array = new ArrayList<>();
}
public void add_val(String s){
array.add(s);
}
public int get_size(){
return array.size();
}
public String get_val(int i){
return array.get(i);
}
}
To make sure the values are filled in, you can check the array size like this:
for (l=0;l<length4;l++){
filled = jsonResponse4.getString(l+"");
fill.add_val(filled);
}
Log.d("TEST", String.valueOf(fill.get_size());
Remove all cases of the static keyword in ArrayClass. Static methods are class level methods, ie. are called on the class itself, rather than an instance of the class.
You can also try this, for ArrayList:
First do some changes in your ArrayClass. Use get And Set method to access your array.
public class ArrayClass {
private ArrayList<String> array = new ArrayList<>();
public ArrayList<String> getArray() {
return array;
}
public void setArray(ArrayList<String> array) {
this.array = array;
}
}
And your other class where you attempt to edit the ArrayList use getArray And SetArray method and some predefined method of ArrayList like this:
Store the data in ArrayList:
for (l=0;l<length4;l++){
filled = jsonResponse4.getString(l+"");
fill.getArray().add(filled);
}
Get Size of ArrayList:
fill.getArray().size();
And also you can store an another ArrayList like
ArrayList<String> tempArrayList = new ArrayList<String>();
tempArrayList.add("string 1");
tempArrayList.add("string 2");
tempArrayList.add("string 3");
tempArrayList.add("string 4");
fill.setArray(tempArrayList)
I have an array: Object[] array, and an array adapter that extends ArrayAdapter<Object>.
When i try to delete from it using adapter.remove(Object obj) i get an UnsupportedOperationException exception, just as this post.
The provided answers suggest using an ArrayList instead. This is not an option for me. I need to stick with array. So i copied the array to another array, but without the item i want to delete. Then i just did:
oldArray = newArray;
and then called adapter.notifyDataSetChanged();.
This works fine except it doesn't refresh the screen. I need to close then reopen the screen to see the changes. Shouldn't notifyDataSetChanged() do the refreshing?
edit:
Following #MD's answer, this is what i'm doing right now:
controller.onRemove(id);
public void onRemove(int id) {
int userListLength = usersArray.length;
int j = 0;
User[] newUserList = new User[userListLength-1];
for(int i=0; i<userListLength; i++)
{
if(id != usersArray[i].getId())
{
newUserList[j] = new User();
newUserList[j] = usersArray[i];
j++;
}
}
usersArray = newUserList;
//store in database
//...
view.getAdapter().refresh( usersArray );
}
public void refresh(User[] items)
{
this.userArray = items;
notifyDataSetChanged();
}
adapter construction:
adapter = new myUserAdapter( controller.getBaseContext(), R.layout.user_row, userArrayList);
usersListView.setAdapter( adapter );
and in myUserAdapter i have:
private User[] userArray;
Solution:
#MD's answer works. But I also had to override getCount() in the adapter:
#Override
public int getCount () {
return userArray.length;
}
It's explained in the accepted answer here.
i have a way
Add refresh method in your adapter:
public void refresh(List<String> items)
{
this.items = items;
notifyDataSetChanged();
}
and call from Activity like
yourAdapter.refresh(items); // items new arrayList or Array
ArrayAdapter simply wraps the List<T> you pass to its constructor and when you call remove(), it calls the remove() method of that list.
If you pass an array instead of a list to the constructor, it converts it with Arrays.asList().
/**
* Constructor
*
* #param context The current context.
* #param resource The resource ID for a layout file containing a TextView to use when
* instantiating views.
* #param objects The objects to represent in the ListView.
*/
public ArrayAdapter(Context context, int resource, T[] objects) {
init(context, resource, 0, Arrays.asList(objects));
}
In older Android versions Arrays.asList returns a readonly list. That's why you get the exception
You must explicitly create an ArrayList out of your array:
adapter = new myUserAdapter( controller.getBaseContext(), R.layout.user_row, new ArrayList<User>(Arrays.asList(userArrayList)));
I have a ListView and ListView adapter. I am adding objects to the adapter but I only want to add one row with an object that contains a certain String. This is my code but it does not work:
public static List<FriendsVideoLVModel> list = new ArrayList<FriendsVideoLVModel>();
#Override
public void add(FriendsVideoLVModel obj) {
super.add(obj);
for (int i=0; i <list.size(); i++) {
if (!obj.eventTitle.equals(list.get(i).eventTitle)) {
list.add(obj);
notifyDataSetChanged();
}
}
}
Please help. The logic looks fine to me but it just does not work. Nothing is in fact added.
The user types 2 letters in the autocomplete text box
Those 2 letters get saved and used in a web service method in order to
retrieve all users who start with those 2 letters
XML result get returned, and get parsed, and we retrieve the user name+ the id and
save each one in different ArrayList
the result from the first name arraylist get puts in an a dropdown list (the autocomplete one)
The user select an item from the drop list items
--
I need to display the name in the drop down list, however, when the user chooses a name, that user ID should be selected and saved as a String in order to be used for another query.
Question is: How to display the name but select the ID for that name
AutoCompleteTextView assigneeInput;
assigneeInput=(AutoCompleteTextView)
findViewById(id.editassignee);
assigneeInput.addTextChangedListener(new
TextWatcher() {
#Override
public void onTextChanged (CharSequence s,int start, int before, int count){
getContactsForAssignee();
}
#Override
public void beforeTextChanged (CharSequence s,int start, int count, int after){
}
#Override
public void afterTextChanged (Editable s){
}
}
);
//Textwatcher for assignee input -end
}
//Method to get Contacts for the assignee autocomplete - Start
public void getContactsForAssignee() {
//webservice call method
}
//Method to get Contacts for the assignee autocomplete - End
public void receiveResults10(String result10) {
try {
//Dom parsing set up
List<String> valSetOne = new ArrayList<String>();
List<String> valSetTwo = new ArrayList<String>();
ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < nodesUDSObjectList.getLength(); i++) {
Element elementUDSObject = (Element) nodesUDSObjectList.item(i);
NodeList nodesAttributeList = elementUDSObject.getElementsByTagName("Attribute");
HashMap<String, String> mapp = new HashMap<String, String>();
for (int iA = 0; iA < nodesAttributeList.getLength(); iA++) {
Element elementAttribute = (Element) nodesAttributeList.item(iA);
//You have attribute(iA)
NodeList AttrNameElementList = (NodeList) elementAttribute.getElementsByTagName("AttrName");
String nameValue = getCharacterDataFromElement((Element) (AttrNameElementList.item(0)));
System.out.println("name" + nameValue);
NodeList AttrValueElementList = (NodeList) elementAttribute.getElementsByTagName("AttrValue");
String valueValue = getCharacterDataFromElement((Element) (AttrValueElementList.item(0)));
if (nameValue.equals("name")) {
valSetOne.add(valueValue);
mapp.put(COMBO_NAME, valueValue);
}
if (nameValue.equals("id")) {
valSetTwo.add(valueValue);
mapp.put(PERSISTENT_ID, valueValue);
}
}
menuItems.add(mapp);
}
AutoCompleteTextView editAssignee;
ArrayAdapter<String> adapter;
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, valSetOne);
editAssignee = (AutoCompleteTextView) findViewById(R.id.editassignee);
editAssignee.setAdapter(adapter);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getCharacterDataFromElement(Element e) {
}
//Beginning of method to actually save the ticket executed on click of the "save" button
public void SaveThisIncident(View v) {
AutoCompleteTextView editAssigneeInput = (AutoCompleteTextView) findViewById(R.id.editassignee); //receiving the users input for assignee
String thisIsAssignee = editAssigneeInput.getText().toString();
}
You need to set itemclicklistner for your AutoCompleteTextView editAssignee & use BaseAdapter instead of ArrayAdapter.
Pass ArrayList of your custom object which contain both id & string value to baseadapter.
Custom object can be
public class item{
String id;
String value;
}
Now onClickItem you can get both id & value from your Arraylist