Call JSON on Spinner OnItemSelected and display data into another Spinner - android

I am making an android app in which I am using two spinners. In first spinner I am displaying data from JSON which I've done successfully. Now by clicking an item of first spinner I need to display data from another JSON service into second spinner.
First Service (I am displaying city_name from this service on first spinner):
{"result":{"data":[{"city_id":"16","city_name":"\u00c4ngelholm"},
{"city_id":"23","city_name":"B\u00e5stad"},
{"city_id":"22","city_name":"Halmstad"},
{"city_id":"19","city_name":"H\u00f6gan\u00e4s"},{"city_id":"20","city_name":"Helsingborg"},
{"city_id":"15","city_name":"Klippan"},
{"city_id":"24","city_name":"Kungsbacka"},
{"city_id":"21","city_name":"Laholm"},{"city_id":"18","city_name":"Landskrona"}],
"status":"true","description":""}}
Second Service:
{"result":{"data":[{"category_id":"18","category":"Aff\u00e4rsverksamhet",
"city_id":"16","city_name":"\u00c4ngelholm"},{"category_id":"19","category":"\u00d6vrigt",
"city_id":"16","city_name":"\u00c4ngelholm"},{"category_id":"13","category":"Bostad",
"city_id":"16","city_name":"\u00c4ngelholm"},{"category_id":"15","category":"Elektronik",
"city_id":"16","city_name":"\u00c4ngelholm"},{"category_id":"12","category":"F\u00f6r hemmet","city_id":"16","city_name":"\u00c4ngelholm"},{"category_id":"11","category":"Fordon",
"city_id":"16","city_name":"\u00c4ngelholm"},
{"category_id":"16","category":"Fritid & Hobby",
"city_id":"16","city_name":"\u00c4ngelholm"}],
"status":"true","description":""}}
As you can see in both services city_id and city_name are common fields. If I select city_name from first spinner it will match through city_id or city_name and display category against that city_name.
Below is my code I have tried.
private class AllCities extends AsyncTask<String, String, JSONObject>
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected JSONObject doInBackground(String... params)
{
try
{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("url of First Service");
HttpResponse resp = client.execute(post);
HttpEntity entity = resp.getEntity();
String response = EntityUtils.toString(entity);
return new JSONObject(response);
}
catch(Exception ex)
{
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(JSONObject result)
{
super.onPostExecute(result);
if(result != null)
{
myList = new ArrayList<HashMap<String,String>>();
if(! result.has("false"))
{
try
{
JSONObject object = result.getJSONObject("result");
JSONArray array = object.getJSONArray("data");
stringArray = new ArrayList<String>();
for(int i=0; i<array.length(); i++)
{
HashMap<String, String> map = new HashMap<String, String>();
map.put("city_id", array.getJSONObject(i).getString("city_id"));
map.put("city_name", array.getJSONObject(i).getString("city_name"));
myList.add(map);
stringArray.add(array.getJSONObject(i).getString("city_name"));
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(PostAdds.this,
android.R.layout.simple_spinner_item, stringArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_city.setAdapter(adapter);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
else if(result == null)
{
Toast.makeText(PostAdds.this,
"Hittade inga Detaljer Vänligen Kontrollera din Internet-anslutning",
Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
//what am I suppose to do here????
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
}

Sorry about the late answer. I was solved this by my self but never came back here to post the solution which worked for me. Now I am posting this answer if any one has same kind of problem can get help from here.
So What I did
1) Call the first service and populate city names on first spinner and when item is selected of first spinner, save its value in a global String like
String selectedCity;
selectedCity = spinner1.getSelectedItem().toString();
2) When click any item of first spinner call the second service and put a simple check while populating the second spinner.
ArrayList<String> categories = new ArrayList<String>();
try {
JSONObject object = result.getJSONObject("result");
JSONArray array = object.getJSONArray("data");
for(int a = 0; a < array.length(); a++) {
String cityName = array.getJSONObject(a).getString("city_name");
if(cityName.equals(selectedCity)) // this check is important
{
categories.add(cityName );
}
}
// after for loop ends populate adapter of second spinner
ArrayAdapter<String> adapt = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, categories);
spinner2.setAdapter(adapt);
}
catch(Exception e) {
e.printStackTrace();
}
In this way I got my desired result. There are other solutions of this problem as well like one of them is when you call second service pass city_id or city_name along with url as params and service will only return you the desired categories.
Hope this will solve for any one has similar kind of problem. I just check my Stackoverflow profile today and found this question has not answered by any one so I did it my self :)

Related

How to use custom Adapter after parsing data from server

ANSWERED BY ME
I am confused where to put and how to use my custom adapter.
My Parser.class has its own Adapter and my MainActivity is passing 3 parameters to the Parser.class (context, url, listview).
(Making my problem simple)
After creating a custom layout, custom adapter, and instantiating my custom adapter, I don't know what to do.
I tried instantiating my custom adapter in my MainActivity then creating MainActivity m = new MainActivity(); in my Parser.class and just use the textviews of my custom listview like m.name_tv.setText(name); and m.price_tv.setText(price) then changing the android.R.layout.simple_list_item_1 to my custom listview layout R.layout.list_layout.
I was just experimenting because I'm having trouble understanding.
Please help.
This is my Parser.class
public class Parser extends AsyncTask<Void,Integer,Integer> {
Context c;
ListView lv;
String data;
ArrayList<String> categories = new ArrayList<>();
ProgressDialog pd;
public Parser(Context c, String data, ListView lv) {
this.c = c;
this.data = data;
this.lv = lv;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(c);
pd.setTitle("Parsing Data");
pd.setMessage("Please Wait...");
pd.show();
}
#Override
protected Integer doInBackground(Void... params) {
return this.parse();
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
if(integer == 1)
{
//ADAPTER
ArrayAdapter<String> adapter = new ArrayAdapter<String>(c, android.R.layout.simple_list_item_1, categories);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position == 0){
}
}
});
}else
{
Toast.makeText(c,"Unable to Parse",Toast.LENGTH_SHORT).show();
}
pd.dismiss();
}
//PARSE RECEIVED DATA
private int parse(){
try
{
//ADD THAT DATA TO JSON ARRAY FIRST
JSONArray ja = new JSONArray(data);
//CREATE JO OBJECT TO HOLD A SINGLE ITEM
JSONObject jo = null;
categories.clear();
//LOOP THROUGH ARRAY
for(int i =0 ; i<ja.length();i++)
{
jo = ja.getJSONObject(i);
//RETRIEVE NAME
name=jo.getString("item_name");
price=jo.getString("item_price");
//ADD TO ARRAY LIST
categories.add(name + " " + price);
}
return 1;
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
}
Should it be better to not separate the classes or it will work the same?
you should get response from web service and parse it (json object or json array) in one step
you can reach this in good way ,
First create class with json attribute name
in your case
Class JsonItem {
string item_name;
string item_price;
// create getter and setter
}
Second use Gson to parse your response
Gson gson = new Gson();
// 1. JSON to Java object, read it from a file.
JsonItem staff = gson.fromJson(YOUR_JSON_Here, JsonItem.class);
that is all

Populate Spinner with JSON

I have found this wonderful JSON Parsing tutorial for Android and since i am fairly new to this area, i would like to ask how can i populate a spinner with the given data. When the user clicks on the name, the rest of them will load up and then again when the user selects one, it must stay active. Any help will be much appriciated!!!
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// we will using AsyncTask during parsing
new AsyncTaskParseJson().execute();
}
// you can make this class as another java file so it will be separated from your main activity.
public class AsyncTaskParseJson extends AsyncTask<String, String, String> {
final String TAG = "AsyncTaskParseJson.java";
// set your json string url here
String yourJsonStringUrl = "http://demo.codeofaninja.com/tutorials/json-example-with-php/index.php";
// contacts JSONArray
JSONArray dataJsonArr = null;
#Override
protected void onPreExecute() {}
#Override
protected String doInBackground(String... arg0) {
try {
// instantiate our json parser
JsonParser jParser = new JsonParser();
// get json string from url
JSONObject json = jParser.getJSONFromUrl(yourJsonStringUrl);
// get the array of users
dataJsonArr = json.getJSONArray("Users");
// loop through all users
for (int i = 0; i < dataJsonArr.length(); i++) {
JSONObject c = dataJsonArr.getJSONObject(i);
// Storing each json item in variable
String firstname = c.getString("firstname");
String lastname = c.getString("lastname");
String username = c.getString("username");
// show the values in our logcat
Log.e(TAG, "firstname: " + firstname
+ ", lastname: " + lastname
+ ", username: " + username);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String strFromDoInBg) {}
}
}
Thanks guys for your help but the real solution lies the following pice of code which needs to be added in the OnPostExecute():
Spinner yourSpinner= (Spinner) findViewById(R.id.yourSpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(<YourActivityNAme>.this, android.R.layout.simple_spinner_item, namesList);
yourSpinner.setAdapter(adapter);
Spinner uses a list object to serve the data. So you should have a backing list to your Spinner object.
Before your for loop, do the following:
List<String> namesList = new ArrayList<String>();
And inside your for loop, add the names to this list:
//I'm assuming you are going to display only the first name
namesList.add(firstName);
Then create an ArrayAdapter object that binds the list to the Spinner.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, namesList);
yourSpinner.setAdapter(adapter);
create list from json such this
List<String> list = new ArrayList<String>();
list.add(json element);
list.add(json element);
list.add(json element);
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, list);
spinner.setAdapter(dataAdapter);

For each key, show value - Android

Im making an app for a site, and i need some help making an for statement. I parse the JSON from the API (Server) and catch it, this is working, however i want it to show in a ListView, i've made my adapter and all that, which is working. Now when i launch the app only one line in the listview shows. So i have no idea on how to get all the values into the listview.
My Activity:
public class FilesActivity extends SherlockActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dblist);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Files");
String response = null;
DefaultHttpClient httpClient = new DefaultHttpClient();
ResponseHandler <String> resonseHandler = new BasicResponseHandler();
HttpPost postMethod = new HttpPost("http://api.bayfiles.net/v1/account/files?session=<SessionId>");
try {
JSONObject json = new JSONObject();
postMethod.setEntity(new ByteArrayEntity(json.toString().getBytes("UTF8")));
postMethod.setHeader( "Content-Type", "application/json" );
response = httpClient.execute(postMethod,resonseHandler);
JSONObject request = new JSONObject(response);
for (Iterator<?> keyIterator = request.keys(); keyIterator.hasNext(); ) {
String key = (String) keyIterator.next();
JSONObject object = request.optJSONObject(key);
ArrayList<fileObject> objectList = new ArrayList<fileObject>();
//ArrayList<fileObject> results = new ArrayList<fileObject>();
if (object != null) {
fileObject obj = new fileObject();
obj.setFileId(key);
obj.setFileName(object.getString("filename"));
obj.setSize(object.getString("size"));
obj.setInfoToken(object.getString("infoToken"));
obj.setDeleteToken(object.getString("deleteToken"));
obj.setSha1(object.getString("sha1"));
objectList.add(obj);
Log.d("log_tag", object.getString("filename"));
}
final ListView lv1 = (ListView) findViewById(R.id.listobjects);
lv1.setAdapter(new MyCustomBaseAdapter(this, objectList));
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object o = lv1.getItemAtPosition(position);
fileObject fullObject = (fileObject)o;
Toast.makeText(FilesActivity.this, "You have chosen: " + " " + fullObject.getFileName(), Toast.LENGTH_LONG).show();
}
});
}
}
catch(Exception e)
{
e.printStackTrace();
Log.d("log_tag", "Error: " + e.toString());
}
}
}
And the adapter and fileObject are just standard, how can i make my listview show all the values?
You are creating a new ArrayListenter code here and a new MyCustomBaseAdapter in every loop iteration. Move that outside of your loop and it will show all the items.
See this: Populating a ListView using an ArrayList?
You're re-creating the arraylist every cycle through the loop. It's only ever going to have one item in it. Just create the ArrayList prior to the for-loop, and populate it inside the loop. Then after you've done that add the whole arraylist to the listview. No need to do it every single cycle. Should look like:
ArrayList<fileObject> objectList = new ArrayList<fileObject>();
for (Iterator<?> keyIterator = request.keys(); keyIterator.hasNext(); ) {
String key = (String) keyIterator.next();
JSONObject object = request.optJSONObject(key);
//ArrayList<fileObject> results = new ArrayList<fileObject>();
if (object != null) {
fileObject obj = new fileObject();
obj.setFileId(key);
obj.setFileName(object.getString("filename"));
obj.setSize(object.getString("size"));
obj.setInfoToken(object.getString("infoToken"));
obj.setDeleteToken(object.getString("deleteToken"));
obj.setSha1(object.getString("sha1"));
objectList.add(obj);
Log.d("log_tag", object.getString("filename"));
}
}//end the for-loop right here. No need to do that other stuff over and over.

How can I update the listview content each time on a button click?

I need to update my ListView content (which is retrieved from a database) each time when a button is clicked. I am trying to include a book search functionality in my android application.
For that I am taking some keywords as input.On a button click the book details matching the key word is retrieved from database and is displayed in the list view in the same layout.
The code I have written will create a new ListView with updated content on each button click and display it below the previous ListView.Which I need to correct.
A preferred solution will be to update the list view content on a button click.
Removing the previously displayed ListView is also acceptable.
For that I tried getListView().inValidate() but didn't work. notifyDataSetChanged() also is not working .Please help :)
public class searchActivity extends ListActivity {
String keyword;
Button bsearch;
EditText input;
JSONParser jParser = new JSONParser();
JSONArray books = null;
SimpleAdapter adapter;
ArrayList<HashMap<String, String>> booksList;
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState{
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
bsearch=(Button)findViewById(R.id.search);
input=(EditText)findViewById(R.id.inputSearch);
booksList = new ArrayList<HashMap<String, String>>();
adapter=newSimpleAdapter(searchActivity.this,booksList,R.layout.search_list,new String[]{"bookname"},new int[] {R.id.bookname});
getListView().setAdapter(adapter);
bsearch.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
keyword=input.getText().toString();
new LoadAll().execute();
}
});
}
class LoadAll extends AsyncTask<String, String, String> {
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("keyword", keyword));
JSONObject json = Jparser.makeHttpRequest("http://10.0.2.2 /libraryconnect/search_book.php", "GET", params);
Log.d("All books: ", json.toString());
try {
int success = json.getInt("success");
if (success == 1) {
books = json.getJSONArray("books");
for (int i = 0; i < books.length(); i++) {
JSONObject c = books.getJSONObject(i);
String name = c.getString("bookname");
HashMap<String, String> map = new HashMap<String, String>();
map.put("bookname",bookname);
booksList.add(map);
}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
runOnUiThread(new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
});
}
}
}
In your onClick(View v), call notifyDataSetChanged () from your adapter
You can change data set of your list view and then call notifyDataSetChanged() on it,instead of creating new list view or new adapter for it.
You can find what you need to know in Android ListView - Tutorial.

Android - Populate list with AsycTaskLoader & MySql

I want to fill a ListFragment with certain objects loaded from my MySql database.
It has to load the first 10 'objects' from my ResultSet.
I want to use an AsyncTaskLoader for this and put the loaded object in a ListItem each time I retreive it from the database.
Can anybody help me with this one? Tried searching for good examples or tutorials but I haven't really found something that's really useful...
Create your adapter with a new list in your preexecute method. Set that adapter to your listview.
Then in doInBackground read your database, create objects to fit in your list, but don't add them. Pas each object after made as parameter for your publishprogress method.
In onProgressUpdate add your object to the list and notify your adapter that the dataset is changed.
Below is an example for how I do it reading a twitter call.
private class parseTwitterTask extends AsyncTask<Void, TCListObject2, List<TCListObject2>> {
TCListObjectAdapter2 adapter;
List<TCListObject2> list;
#Override
protected void onPreExecute() {
list = new ArrayList<TCListObject2>();
ListView lv = (ListView)findViewById(R.id.twitterlist);
adapter = new TCListObjectAdapter2(list);
lv.setAdapter(adapter);
super.onPreExecute();
}
#Override
protected List<TCListObject2> doInBackground(Void... params) {
try {
String url = social.get("twittersearchurl");//"http://search.twitter.com/search.json?q=" + social.get("twitter");
String json = Internet.request(url, null);
JSONObject jo = new JSONObject(json);
if(jo.has("results")) {
JSONArray ar = jo.getJSONArray("results");
for(int i = 0; i < ar.length(); i++) {
TCListObject2 tweet = new TCListObject2();
JSONObject jobj = (JSONObject) ar.get(i);
tweet.id = "false";
tweet.img = jobj.getString("profile_image_url");
String text = jobj.getString("text");
text = Html.fromHtml(text).toString();
tweet.params.put(R.id.sub2, text);
String name = jobj.getString("from_user");
name = Html.fromHtml(name).toString();
tweet.params.put(R.id.text, name);
String time = jobj.getString("created_at");
tweet.params.put(R.id.sub1, Converter.timeToTimeAgo(time));
try {
tweet.time = new Date(time);
} catch(Exception e) {
e.printStackTrace();
}
tweet.celLayout = R.layout.cell_tweetobject;
publishProgress(tweet);
}
}
} catch(Exception e) {
e.printStackTrace();
}
return list;
}
#Override
protected void onProgressUpdate(TCListObject2... values) {
list.add(values[0]);
adapter.notifyDataSetChanged();
super.onProgressUpdate(values);
}

Categories

Resources