Kevin Pham Kevin Pham - 1 month ago 8
Android Question

setOnItemSelectedListener not being called?

I'm new to Android and was working on my first app. I was trying to parse the contents of a Google Sheets spreadsheets, specifically a list of names into a

Spinner
. I've done so successfully by using an
ArrayAdapter
with an
ArrayList
as I can see the options when I expand the
Spinner
. The problem I'm facing is that the
Spinner
doesn't show the currently selected item when one is selected. If you try to run my code, you'll see that if you try to click the submit
Button
, it'll tell you that
null
is being selected, so I've narrowed down my problem to the currently selected name String not being selected.

Here is my MainActivity class:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

ArrayList<String> names = new ArrayList<String>();

Spinner spBusinessType;
Button btnsubmit;

ArrayAdapter<String> adapterBusinessType;

String sbusinesstype;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

spBusinessType = (Spinner) findViewById(R.id.spBussinessType);

btnsubmit=(Button)findViewById(R.id.submit);
btnsubmit.setOnClickListener(this);

new DownloadWebpageTask(new AsyncResult() {
@Override
public void onResult(JSONObject object) {
processJson(object);
}
}).execute("https://spreadsheets.google.com/tq?key=1JKU2Vt_gMNUYYALct4m9xElLdpGlQ3N4uhS9qFRzxOQ");

adapterBusinessType = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, names);
adapterBusinessType.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spBusinessType.setAdapter(adapterBusinessType);

spBusinessType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

@Override
public void onItemSelected(AdapterView<?> adapter, View v,
int position, long id) {
// On selecting a spinner item
sbusinesstype = adapter.getItemAtPosition(position).toString();
System.out.println(sbusinesstype);

// Showing selected spinner item
Toast.makeText(getApplicationContext(),
"Bussiness Type : " + sbusinesstype, Toast.LENGTH_SHORT).show();
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub

}
});

}

@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "You have selected " + sbusinesstype,Toast.LENGTH_SHORT).show();
}

private void processJson(JSONObject object) {

try {
JSONArray rows = object.getJSONArray("rows");

for (int r = 0; r < rows.length(); ++r) {
JSONObject row = rows.getJSONObject(r);
JSONArray columns = row.getJSONArray("c");

String name = columns.getJSONObject(0).getString("v");
names.add(name);
}

} catch (JSONException e) {
e.printStackTrace();
}
}


the AsyncResult interface I'm using to obtain a
JSON
object from Google Sheets:

public interface AsyncResult
{
void onResult(JSONObject object);
}


the DownloadWebpageTask class that is obtaining and parsing the JSON object:

public class DownloadWebpageTask extends AsyncTask<String, Void, String> {
AsyncResult callback;

public DownloadWebpageTask(AsyncResult callback) {
this.callback = callback;
}

@Override
protected String doInBackground(String... urls) {

// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to download the requested page.";
}
}

// onPostExecute displays the results of the AsyncTask.
@Override
protected void onPostExecute(String result) {
// remove the unnecessary parts from the response and construct a JSON
int start = result.indexOf("{", result.indexOf("{") + 1);
int end = result.lastIndexOf("}");
String jsonResponse = result.substring(start, end);
try {
JSONObject table = new JSONObject(jsonResponse);
callback.onResult(table);
} catch (JSONException e) {
e.printStackTrace();
}
}

private String downloadUrl(String urlString) throws IOException {
InputStream is = null;

try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int responseCode = conn.getResponseCode();
is = conn.getInputStream();

String contentAsString = convertStreamToString(is);
return contentAsString;
} finally {
if (is != null) {
is.close();
}
}
}

private String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();

String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}


the activity_main layout file:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<include layout="@layout/content_main" />

</RelativeLayout>


and the content_main layout file that I put the Spinner in:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity">
tools:showIn="@layout/activity_main">

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Select Business Type"
android:textColor="#000000"
android:textSize="20sp" />

<Spinner
android:id="@+id/spBussinessType"
style="@style/Base.Widget.AppCompat.Spinner.Underlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"></Spinner>

<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:text="Submit"
android:textSize="15sp" />

</LinearLayout>


What is causing the adapter to not detect when one of the name strings is being selected? Could it be related to how I'm parsing them from the Google Sheet?

Answer

You didnt notify the ArrayAdapter that the data has changed, you originally passed empty Arraylist and upon filling the array list, you have to notifiy the Adapter that data has changed and its time for it to consider that, something like

private void processJson(JSONObject object) {
    try {
        JSONArray rows = object.getJSONArray("rows");

        for (int r = 0; r < rows.length(); ++r) {
            JSONObject row = rows.getJSONObject(r);
            JSONArray columns = row.getJSONArray("c");

            String name = columns.getJSONObject(0).getString("v");
            names.add(name);
        }
        adapterBusinessType.notifyDataSetChanged();
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

That should help.

Comments