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?
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.
It would appear no data is being displayed in your Adapter. Nothing can be selected. Your listener code looks fine.
Put adapterBusinessType.notifyDatasetChanged() into the processJson method. Outside the catch or after you add all the data to the list.
Or... replace names.add with adapterBusinessType.add
Related
I have problem when i get the list from server i want to check it, if it's any object there or not.
if there are object , appears in my layout text : there is no object after few seconds it's disappears
and show my list.
i want just if there is object will appear in my layout directly.
private class RetrieveTask extends AsyncTask> {
#Override
protected List<branch> doInBackground(String... params) {
manager = new SessionManager(getActivity().getApplicationContext());
manager.checkLogin();
HashMap<String, String> user = manager.getUserID();
String uid = user.get(SessionManager.KEY_uid);
// Intent intent= getActivity().getIntent(); // gets the previously created intent
//String type18 = intent.getStringExtra("key28");
String strUrl =
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(strUrl);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("markers");
////////////////////////////////////////
List<branch> bList = new ArrayList<>();
Gson gson = new Gson();
for (int i = 0; i < parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);
/////////market object
market mr = new market(Integer.valueOf(finalObject.getString("id")), finalObject.getString("mName")
, finalObject.getString("pic"));
/////////location object
location lo = new location(Float.valueOf(finalObject.getString("lat")), Float.valueOf(finalObject.getString("lng"))
, finalObject.getString("area"), finalObject.getString("city"));
/////////(branch object) inside it (market object)
branch it = new branch(Integer.valueOf(finalObject.getString("bid")), Integer.valueOf(finalObject.getString("phone"))
, finalObject.getString("ser"), Integer.valueOf(finalObject.getString("dis")), Integer.valueOf(finalObject.getString("brNo"))
, Float.valueOf(finalObject.getString("rating")), mr, lo,true);
/*//////////add marker
LatLng latlng = new LatLng(Double.valueOf(finalObject.getString("lat")), Double.valueOf(finalObject.getString("lng")));
addMarker(latlng, Integer.valueOf(finalObject.getString("bid")));*/
// adding the branch object in the list
bList.add(it);
}
return bList;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
here the postExcute
#Override
protected void onPostExecute(final List<branch> result) {
super.onPostExecute(result);
if (result != null) {
final itemAdapter adapter = new itemAdapter(getActivity().getApplicationContext(), R.layout.row_favmarkets, result);
lv.setAdapter(adapter);
}
}
}
this is my layout xml
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="4dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingTop="4dp"
tools:context="com.gmplatform.gmp.favouriteitem">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="250dp"
android:text="There is no Markets in your Favourite List.."
android:textSize="24sp"
android:visibility="gone" />
</LinearLayout>
<ListView
android:id="#+id/l20"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:horizontalSpacing="3dp"
android:numColumns="3"
android:verticalSpacing="0dp" />
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button6"
android:layout_marginLeft="400dp" />
Suggested changes which will at first show nothing when the request is executed. Once completed, if the list is empty it'll show "There is no Markets in your Favourite List..", otherwise the list will show.
Part Layout XML:
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/linearLayout28">
<TextView
android:id="#+id/textView28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="250dp"
android:text="There is no Markets in your Favourite List.."
android:textSize="24sp"
android:visibility="gone" />
</LinearLayout>
Initialize linearLayout28:
LinearLayout linearLayout28 = findViewById(R.id.linearLayout28);
And changes for the AsyncTask:
private class RetrieveTask extends AsyncTask<Void, Void, List<branch>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
lv.setVisibility(View.GONE);
linearLayout28.setVisibility(View.GONE);
}
#Override
protected List<branch> doInBackground(String... params) {
//Keep as your code
...
}
#Override
protected void onPostExecute(final List<branch> result) {
super.onPostExecute(result);
if (result != null && result.size() != 0) {
final itemAdapter adapter = new itemAdapter(
getActivity().getApplicationContext(),
R.layout.row_favmarkets, result);
lv.setAdapter(adapter);
lv.setVisibility(View.VISIBLE);
linearLayout28.setVisibility(View.GONE);
} else {
lv.setVisibility(View.GONE);
linearLayout28.setVisibility(View.VISIBLE);
}
}
}
You are basically on the solution but you should not update the user interface from your AsyncTask. Create an interface and implement it on the Activity. Let the activity to update the data on the UI when data is ready or show a message error.
As an example, define the interface in your AsyncTask like:
private TaskCallback listener = null;
public interface TaskCallback {
void OnTaskCompleted ();
}
public void setListener (TaskCallback listener) {
this.listener = listener;
}
When your task was completed:
#Override
public void onPostExecute (Void v) {
if (listener != null) {
listener.OnTaskCompleted ();
}
}
You can add parameters to your callback base on your needs.
At your Activity level:
public class YourActivity extends Activity implements YourTask.TaskCallback {
// When you execute your task add the reference to the listener
YourTask task = new YourTask (YourActivity.this);
task.setListener (YourActivity.this);
task.execute ();
#Override
public void OnTaskCompleted () {
// Update your screen or show an error message
}
}
I am trying to search a JSON data fetched from a URL, but whenever the user types a search string the application crashes. How do I fix it?
Here is my code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private String TAG = MainActivity.class.getSimpleName();
private ProgressDialog pDialog;
private ListView lv;
private EditText filterText;
private ArrayAdapter<String> listAdapter;
// URL to get contacts JSON
private static String url = "http://210.213.86.195:14344/inventory/getallitemname";
ArrayList<HashMap<String, String>> itemList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
filterText = (EditText)findViewById(R.id.editText);
itemList = new ArrayList<>();
lv = (ListView) findViewById(R.id.list_item);
new GetItems().execute();
filterText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
MainActivity.this.listAdapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
}
}
);
}
/**
* Async task class to get json by making HTTP call
*/
private class GetItems extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray items = jsonObj.getJSONArray("Data");
// looping through All Contacts
for (int i = 0; i < items.length(); i++) {
JSONObject c = items.getJSONObject(i);
String ItemCode = c.getString("ItemCode");
String ItemName = c.getString("ItemName");
// tmp hash map for single item
HashMap<String, String> item = new HashMap<>();
// adding each child node to HashMap key => value
item.put("ItemCode", ItemCode);
item.put("ItemName", ItemName);
// adding item to item list
itemList.add(item);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, itemList,
R.layout.list_item, new String[]{"ItemCode", "ItemName"}, new int[]{R.id.ItemCode,
R.id.ItemName});
lv.setAdapter(adapter);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.jsonparser.MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ListView
android:id="#+id/list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp"
android:layout_below="#+id/editText"
android:layout_alignLeft="#+id/editText"
android:layout_alignStart="#+id/editText" />
</RelativeLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="#dimen/activity_horizontal_margin">
<TextView
android:id="#+id/ItemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:paddingTop="6dip"
android:textColor="#color/colorPrimaryDark"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/ItemCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:textColor="#color/colorAccent" />
</LinearLayout>
you have not initalized it anywhere in code:-
MainActivity.this.listAdapter
so default is null,in postExecute you are using local adapter variable.
Put
adapter = new ArrayAdapter<String>(this,
R.layout.list_view_rows, R.id.listview, ListofStringYouWantToDisplay);
below
lv = (ListView) findViewById(R.id.list_item);
hear - ListofStringYouWantToDisplay is String[] or ArrayList you want to display
Your problem is you not initializing adapter before use
I'm following this tutorial http://javatechig.com/android/android-recyclerview-example
while after done coding, i'm getting one error android.view.View cannot be cast to android.support.v7.widget.RecyclerView. thanks in advance
My MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "RecyclerViewExample";
private List<FeedItem> feedsList;
private RecyclerView mRecyclerView;
private MyRecyclerAdapter adapter;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize recycler view
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerd_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setVisibility(View.VISIBLE);
// Downloading data from below url
final String url = "http://javatechig.com/?json=get_recent_posts&count=45";
new AsyncHttpTask().execute(url);
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
setProgressBarIndeterminateVisibility(true);
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
// Download complete. Let us update UI
progressBar.setVisibility(View.GONE);
if (result == 1) {
adapter = new MyRecyclerAdapter(MainActivity.this, feedsList);
mRecyclerView.setAdapter(adapter);
} else {
Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
}
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
feedsList = new ArrayList<>();
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
FeedItem item = new FeedItem();
item.setTitle(post.optString("title"));
item.setThumbnail(post.optString("thumbnail"));
feedsList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:class="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:id="#+id/relativ"
tools:context="com.example.ict4.recyclerviewasyntask.MainActivity">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerd_view"
android:layout_centerInParent="true"
class="android.support.v7.widget.RecyclerView"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/progress_bar"
android:layout_centerInParent="true"
/>
</RelativeLayout>
In your XML layout, change
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerd_view"
android:layout_centerInParent="true"
class="android.support.v7.widget.RecyclerView"/>
to
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerd_view"
android:layout_centerInParent="true" />
I am currently making an app for android and I have a problem where the UI on a new activity that I start from the main one does not show up. I have no idea what the problem is.
Here is my second activity's layout xml file:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/TableLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.tabcards.android.Search" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
>
<TableLayout
android:id="#+id/tableScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="yes"
android:padding="5dp"
android:background="#color/gray">
</TableLayout>
</ScrollView>
</TableRow>
Here is my acitiviy's code:
public class Search extends ActionBarActivity {
TableLayout tableScrollView;
String[] JSONExceptions = { "type", "em", "user_id", "id", "profilepic", "bg"};
String value;
JSONObject jObject;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
Bundle extras = getIntent().getExtras();
if (extras != null) {
value = extras.getString("id");
}
System.out.println(value);
tableScrollView = (TableLayout) findViewById(R.id.tableScrollView);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
jObject = getJson("http://www.tabcards.com/req/androidapi/L2o30H8JlFMtFYHW3KLxkts20ztc5Be6Z6m6v315/json/"
+ value);
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
new Thread(new Runnable() {
#Override
public void run() {
try {
createUI(jObject);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
System.out.println("complete");
}
private void createUI(JSONObject jObject) throws JSONException {
Iterator<?> keys = jObject.keys();
int absIndex = 0;
while( keys.hasNext() ){
String key = (String)keys.next();
if(!contains2(JSONExceptions , jObject.get(key))){
String value = jObject.getString(key);
System.out.println("level 1");
if(value!="") {
insertElement(key + " : " + value, absIndex++);
}
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search, menu);
return true;
}
private void insertElement(String data, int i) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View newRow = inflater.inflate(R.layout.row, null, false);
newRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
TextView dataTextView = (TextView) newRow
.findViewById(R.id.rowTextView);
dataTextView.setText(data);
System.out.println(dataTextView.getText().toString());
tableScrollView.addView(newRow, i);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private InputStream downloadUrl(String urlString) throws IOException {
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();
return conn.getInputStream();
}
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public static JSONObject getJson(String url){
InputStream is = null;
String result = "";
JSONObject jsonObject = null;
// HTTP
try {
HttpClient httpclient = new DefaultHttpClient(); // for port 80 requests!
HttpPost httppost = new HttpPost(url);
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch(Exception e) {
return null;
}
// Read response to string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"utf-8"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
System.out.println(line);
}
is.close();
result = sb.toString().replace("[", "");
} catch(Exception e) {
return null;
}
// Convert string to object
try {
jsonObject = new JSONObject(result.replace("]", ""));
} catch(JSONException e) {
return null;
}
return jsonObject;
}
This is how I am creating the activity:
Intent i = new Intent(getApplicationContext(), Search.class);
i.putExtra("id",searchEditText.getText().toString());
startActivity(i);
Tell me if you need any more info.
problem:
thread.join();
That problem is dreadlock you are waiting for thread to be done executing, which will put your UI thread to the Blocking state like Thread.Sleep() thus UI thread is waiting for your request to be done executing before it can display the layout in the screen.
from documentation:
Like sleep, join responds to an interrupt by exiting with an InterruptedException.
solution:
Use only one thread which will still wait for the request(createUI) and executes your createUI method after.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
jObject = getJson("http://www.tabcards.com/req/androidapi/L2o30H8JlFMtFYHW3KLxkts20ztc5Be6Z6m6v315/json/"
+ value);
createUI(jObject);
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
I am trying to use Chris Banes' library Actionbar-PullToRefresh. It can be found here.
I am using Tabs at bottom of screen in my app. as you can see in screen shot.
I read through the sample code. He says that all you have to do is, wrap your refreshable view in a PullToRefreshLayout like this: How do i integrate it into my app.
public class MainActivity extends Activity implements OnTabChangeListener {
private TabHost mTabHost;
public static final String TAB_1 = "Open";
public static final String TAB_2 = "Approved";
public static final String TAB_3 = "Decline";
private int mCurrentTab;
public String result;
Vector<String> msgvector = new Vector<String>();
Vector<String> usernamevector = new Vector<String>();
Vector<String> feedIdvector = new Vector<String>();
Vector<String> userIdvector = new Vector<String>();
ListView listview,listview1,listview2;
private ProgressDialog simpleWaitDialog;
List<Rowfeeds> rowfeedlist;
public String result2;
public String result3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
listview = (ListView)findViewById(R.id.tab_1);
listview1 = (ListView)findViewById(R.id.tab_2);
listview2 = (ListView)findViewById(R.id.tab_3);
new Feedsdata().execute();
setupTabs();
mTabHost.setOnTabChangedListener(this);
mTabHost.setCurrentTab(mCurrentTab);
}
private class Feedsdata extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
try {
Log.i("doInBackground", "doInBackground");
HttpClient hc = new DefaultHttpClient();
HttpPost postMethod = new HttpPost("http://192.168.21.74/mynetwork/formapi/top_feeds");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("from", "0"));
nameValuePairs.add(new BasicNameValuePair("to", "10"));
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse rp = hc.execute(postMethod);
if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(rp.getEntity());
Log.v("suggestion_data", "" + result);
JSONArray jsonary = new JSONArray(result);
for (int i = 0; i < jsonary.length(); i++) {
//Log.v("jsonary.length", "" +jsonary.length());
String sr = ""+jsonary.getJSONObject(i);
//Log.v("sr", "" +sr);
JSONObject jobj = new JSONObject(sr);
Log.v("======================", "=================" );
Log.v("feed_id", "" +jobj.getString("feed_id"));
Log.v("feed_message", "" +jobj.getString("feed_message"));
Log.v("user_id", "" +jobj.getString("user_id"));
Log.v("username", "" +jobj.getString("username"));
Log.v("======================", "=================" );
msgvector.add(""+jobj.getString("feed_message").toString().trim());
usernamevector.add("" +jobj.getString("username").toString().trim());
feedIdvector.add("" +jobj.getString("feed_id").toString().trim());
userIdvector.add("" +jobj.getString("user_id").toString().trim());
}
//for (int i = 0; i < feedIdvector.size(); i++) {
//Log.v("feedIdvector", "" +feedIdvector.elementAt(i));
//}
}else{
Log.d("JSON", "StatusCode "+rp.getStatusLine().getStatusCode());
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.i("AsyncTaskException", e.toString());
}
Log.i("popularAsyncTaskException", e.toString());
}
return null;
}
#Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
simpleWaitDialog = ProgressDialog.show(MainActivity.this,"Wait", "Downloading feeds");
}
#Override
protected void onPostExecute(String result) {
rowfeedlist = new ArrayList<Rowfeeds>();
for (int i = 0; i < msgvector.size(); i++) {
Rowfeeds rowfeeds = new Rowfeeds(msgvector.elementAt(i),usernamevector.elementAt(i),feedIdvector.elementAt(i));
rowfeedlist.add(rowfeeds);
}
Customfeedadapter feedadapter = new Customfeedadapter(getApplicationContext(),R.layout.feeds,rowfeedlist
,feedIdvector,userIdvector);
listview.setAdapter(feedadapter);
simpleWaitDialog.dismiss();
}
private void setupTabs() {
mTabHost.setup(); // you must call this before adding your tabs!
mTabHost.addTab(newTab(TAB_1, R.id.tab_1));
mTabHost.addTab(newTab(TAB_2, R.id.tab_2));
mTabHost.addTab(newTab(TAB_3, R.id.tab_3));
}
private TabSpec newTab(String tag, int tabContentId) {
Log.i("tag", tag);//fff498
Log.i("tabContentId", ""+tabContentId);//fff498
TabSpec spec = mTabHost.newTabSpec(tag);
spec.setContent(tabContentId);
if(tag.equalsIgnoreCase("Open")){
spec.setIndicator("", getResources().getDrawable(R.drawable.feed));
spec.setContent(tabContentId);
}else if(tag.equalsIgnoreCase("Approved")){
spec.setIndicator("", getResources().getDrawable(R.drawable.trend));
spec.setContent(tabContentId);
}else if(tag.equalsIgnoreCase("Decline")){
spec.setIndicator("", getResources().getDrawable(R.drawable.popularr));
spec.setContent(tabContentId);
}
for(int i=0;i<mTabHost.getTabWidget().getChildCount();i++)
{
mTabHost.getTabWidget().getChildAt(0).setBackgroundColor(Color.parseColor("#fff498"));
}
return spec;
}
public void onTabChanged(String tabId) {
for(int i=0;i<mTabHost.getTabWidget().getChildCount();i++)
{
mTabHost.getTabWidget().getChildAt(i).setBackgroundColor(Color.WHITE);
}
if (TAB_1.equals(tabId)) {
// updateTab(R.id.tab_1);
mCurrentTab = 0;
//Toast.makeText(getApplicationContext(), "1No Guest list for Today", Toast.LENGTH_SHORT).show();
mTabHost.getTabWidget().getChildAt(mTabHost.getCurrentTab()).setBackgroundColor(Color.parseColor("#fff498"));
}
if (TAB_2.equals(tabId)) {
//updateTab(R.id.tab_2);
mCurrentTab = 1;
//Toast.makeText(getApplicationContext(), "2No Guest list for Today", Toast.LENGTH_SHORT).show();
mTabHost.getTabWidget().getChildAt(mTabHost.getCurrentTab()).setBackgroundColor(Color.parseColor("#fff498"));
//http://192.168.21.74/mynetwork/formapi/trending
//http://192.168.21.74/mynetwork/formapi/popular
}
if (TAB_3.equals(tabId)) {
//updateTab(R.id.tab_2);
mCurrentTab = 2;
// Toast.makeText(getApplicationContext(), "3No Guest list for Today", Toast.LENGTH_SHORT).show();
mTabHost.getTabWidget().getChildAt(mTabHost.getCurrentTab()).setBackgroundColor(Color.parseColor("#fff498"));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Xml layout:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<ListView
android:id="#+id/tab_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="#+id/tab_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="#+id/tab_3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</FrameLayout>
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0" >
</TabWidget>
</LinearLayout>
</TabHost>
Put all your list views in PullToRefreshLayout and give R.id.tab_1 R.id.tab_2 R.id.tab_3 id's to your PullToRefreshLayout instead of ListView
<uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tab_1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/listview1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout>
same for rest of the listview
In java inside onCreate of the activity:
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mPullToRefreshLayout= (ListView)findViewById(R.id.tab_1);
mPullToRefreshLayout1 = (ListView)findViewById(R.id.tab_2);
mPullToRefreshLayout2 = (ListView)findViewById(R.id.tab_3);
listview = (ListView)findViewById(R.id.listview1);
listview1 = (ListView)findViewById(R.id.listview2);
listview2 = (ListView)findViewById(R.id.listview3);
ActionBarPullToRefresh.from(this)
// Mark All Children as pullable
.allChildrenArePullable()
// Set the OnRefreshListener
.listener(this)
// Finally commit the setup to our PullToRefreshLayout
.setup(mPullToRefreshLayout);
on tab change:
public void onTabChanged(String tabId) {
for(int i=0;i<mTabHost.getTabWidget().getChildCount();i++)
{
mTabHost.getTabWidget().getChildAt(i).setBackgroundColor(Color.WHITE);
}
if (TAB_1.equals(tabId)) {
// updateTab(R.id.tab_1);
mCurrentTab = 0;
//Toast.makeText(getApplicationContext(), "1No Guest list for Today", Toast.LENGTH_SHORT).show();
mTabHost.getTabWidget().getChildAt(mTabHost.getCurrentTab()).setBackgroundColor(Color.parseColor("#fff498"));
ActionBarPullToRefresh.from(this)
// Mark All Children as pullable
.allChildrenArePullable()
// Set the OnRefreshListener
.listener(this)
// Finally commit the setup to our PullToRefreshLayout
.setup(mPullToRefreshLayout);
}
if (TAB_2.equals(tabId)) {
//updateTab(R.id.tab_2);
mCurrentTab = 1;
//Toast.makeText(getApplicationContext(), "2No Guest list for Today", Toast.LENGTH_SHORT).show();
mTabHost.getTabWidget().getChildAt(mTabHost.getCurrentTab()).setBackgroundColor(Color.parseColor("#fff498"));
//http://192.168.21.74/mynetwork/formapi/trending
//http://192.168.21.74/mynetwork/formapi/popular
ActionBarPullToRefresh.from(this)
// Mark All Children as pullable
.allChildrenArePullable()
// Set the OnRefreshListener
.listener(this)
// Finally commit the setup to our PullToRefreshLayout
.setup(mPullToRefreshLayout1);
}
if (TAB_3.equals(tabId)) {
//updateTab(R.id.tab_2);
mCurrentTab = 2;
// Toast.makeText(getApplicationContext(), "3No Guest list for Today", Toast.LENGTH_SHORT).show();
mTabHost.getTabWidget().getChildAt(mTabHost.getCurrentTab()).setBackgroundColor(Color.parseColor("#fff498"));
ActionBarPullToRefresh.from(this)
// Mark All Children as pullable
.allChildrenArePullable()
// Set the OnRefreshListener
.listener(this)
// Finally commit the setup to our PullToRefreshLayout
.setup(mPullToRefreshLayout2);
}
}