Android ListView update after asynctask - android

I have a problem with my adapter for my listview, i don't know where i have to add notifyDataSetChanged() in my code always if i run this code in logcat is coming a error:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(2131165276, class android.widget.ListView)]
my asynctask:
class UpdateData extends AsyncTask<Void, Void, JSONArray> {
String result = "";
JSONArray jArray = null;
#Override
protected void onPostExecute(JSONArray result) {
super.onPostExecute(result);
adapter.addAll(deptList);
adapter.notifyDataSetChanged();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected JSONArray doInBackground(Void... arg0) {
....
try {
JSONArray array = new JSONArray(result);
for (int i = 0; i < array.length(); i++) {
JSONObject j = array.getJSONObject(i);
EventCalendarStrings d = new EventCalendarStrings();
d.name = j.optString("name", "");
d.kategorie = j.optString("Art", "");
deptList.add(d);
}
} catch (JSONException e) {
Log.e("log_tag", "No connection " + e.toString());
}
}
return jArray;
}

It goes in onPostExecute() because it is executed on the UI thread. Calling it in doInBackground() will result in that exception.

Try this
#Override
protected void onPostExecute(JSONArray result) {
super.onPostExecute(result);
runOnUiThread(new Runnable(){
public void run(){
adapter.addAll(deptList);
adapter.notifyDataSetChanged();
}
});
}
or
#Override
protected void onPostExecute(JSONArray result) {
super.onPostExecute(result);
runOnUiThread(new Runnable(){
public void run(){
adapter.addAll(deptList);
listview.setAdapater(adapter);
}
});
}

Related

In AsyncTask server's data is not getting on first time in android

I am trying to get data from server using AsyncTask, on first time result not showing, but its working from second time. I seen so many examples but none of them working for me. please see my code below
private void event_load_data_from_server(int id){
AsyncTask<Integer,Void,Void> task = new AsyncTask<Integer, Void, Void>() {
#Override
protected Void doInBackground(Integer... integers) {
OkHttpClient client = new OkHttpClient();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("http://api.zesteve.com/posteventlist.php?city="+ucl+"&eveid="+eveid+"&id="+integers[0])
.build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
for (int i=0; i<array.length(); i++){
JSONObject object =array.getJSONObject(i);
if(object.has("name")){
pname=object.getString("name");
}else{
pname="";
}
if(object.has("timestamp")){
timestamp =object.getString("timestamp");
}else{
timestamp="";
}
if(object.has("id")){
eveid=object.getInt("id");
}else {
eveid=0;
}
if(object.has("address")){
address=object.getString("address");
}else {
address="";
}
if(object.has("thumbnail")){
thumbnail=object.getString("thumbnail");
}else {
thumbnail="";
}
EventPost events = new EventPost(pname, eveid, thumbnail,address,timestamp);
eventPostList.add(events);
}
}catch (IOException e){
e.printStackTrace();
} catch (JSONException e) {
System.out.println("End of Catagory");
}
return null;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
progressDialog.setMessage("Events Loading Wait...");
showDialog();
}
#Override
protected void onPostExecute(Void aVoid) {
hideDialog();
adapter.notifyDataSetChanged();
}
};
task.execute(id);
}
Whenever you want to use onPostExecute() method in AsyncTask, just make sure use String or other type instead of Void as result parameter of AsyncTask<x, y, String> where x,y are any data type(Integer,String,etc..).
Therefore, make changes in code as per below:
Make both AsyncTask<...> like this AsyncTask<Integer,Void,String>
Change return type of doInBackground from Void to String
Change return null; with return ""; at last line in doInBackground.
Change onPostExecute(Void aVoid) to onPostExecute(String s) for override function of onpostexecute.
Then try it.
private void event_load_data_from_server(int id){
AsyncTask<Integer,Void,JSONArray> task = new AsyncTask<Integer, Void, JSONArray>() {
OkHttpClient client = new OkHttpClient();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("http://api.zesteve.com/posteventlist.php?city="+ucl+"&eveid="+eveid+"&id="+integers[0])
.build();
#Override
protected JSONArray doInBackground(Object... integers) {
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
return array;
}catch (IOException e){
e.printStackTrace();
} catch (JSONException e) {
System.out.println("End of Catagory");
}
return null;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
progressDialog.setMessage("Events Loading Wait...");
showDialog();
}
#Override
protected void onPostExecute(JSONArray array) {
for (int i=0; i<array.length(); i++){
JSONObject object =array.getJSONObject(i);
if(object.has("name")){
pname=object.getString("name");
}else{
pname="";
}
if(object.has("timestamp")){
timestamp =object.getString("timestamp");
}else{
timestamp="";
}
if(object.has("id")){
eveid=object.getInt("id");
}else {
eveid=0;
}
if(object.has("address")){
address=object.getString("address");
}else {
address="";
}
if(object.has("thumbnail")){
thumbnail=object.getString("thumbnail");
}else {
thumbnail="";
}
EventPost events = new EventPost(pname, eveid, thumbnail,address,timestamp);
eventPostList.add(events);
}
hideDialog();
adapter.notifyDataSetChanged();
}
};
task.execute(id);
}

Android: notifyDataSetChanged not working

Hello guys I am doing the delete function in my project and it seems that the notifyDataSetChanged is not working. I've already done some research about this but I don't quiet understand
here is my code in onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_dropped_student);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SharedPreferences preferences = getSharedPreferences("MyApp", MODE_PRIVATE);
subj_code = preferences.getString("code", "UNKNOWN");
subj_code_lab = preferences.getString("code_lab", "UNKNOWN");
studentList = new ArrayList<HashMap<String, String>>();
mylistView = (ListView) findViewById(R.id.list);
arrayAdapter = new StudAdapter(this, stud_List);
mylistView.setAdapter(arrayAdapter);
new LoadStudent().execute();
mylistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String studentId = ((TextView) (view.findViewById(R.id.stud_id))).getText().toString();
final String studentName = ((TextView) (view.findViewById(R.id.studName))).getText().toString();
class AttemptGetData extends AsyncTask<String, String, String>{
String code = subj_code.toString();
String id = studentId;
String stud_name = studentName;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ViewDroppedStudent.this);
pDialog.setMessage("In Progress...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected String doInBackground(String... params) {
JSONParser jsonParser = new JSONParser();
String url = null;
try {
url = "http://192.168.22.3/MobileClassRecord/undroppedStudent.php?stud_id="+ URLEncoder.encode(id, "UTF-8")+"&subj_code="+ URLEncoder.encode(subj_code, "UTF-8");
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
List<NameValuePair> mList = new ArrayList<NameValuePair>();
mList.add(new BasicNameValuePair("stud_id", id));
mList.add(new BasicNameValuePair("subj_code", code));
JSONObject jsonObject = jsonParser.makeHttpRequest(url, "POST", mList);
Log.d("Undrop Student", jsonObject.toString());
try {
verify = jsonObject.getString("Message");
return verify;
}catch (JSONException e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pDialog.dismiss();
if (s != null){
Toast.makeText(getApplicationContext(), verify, Toast.LENGTH_LONG).show();
}
}
}
final MaterialDialog materialDialog = new MaterialDialog(ViewDroppedStudent.this);
materialDialog.setTitle("Undrop Student");
materialDialog.setMessage("Name: " + studentName);
materialDialog.setPositiveButton("UNDROP", new View.OnClickListener() {
#Override
public void onClick(View v) {
materialDialog.dismiss();
new AttemptGetData().execute();
arrayAdapter.notifyDataSetChanged();
}
}).setNegativeButton("CANCEL", new View.OnClickListener() {
#Override
public void onClick(View v) {
materialDialog.dismiss();
}
});
materialDialog.show();
}
});
}
any help would be much appreciated :)
You need to write arrayAdapter.notifyDataSetChanged(); in onPostExecute method
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pDialog.dismiss();
if (s != null){
Toast.makeText(getApplicationContext(), verify, Toast.LENGTH_LONG).show();
}
arrayAdapter.notifyDataSetChanged();
}
Remove perticular data from your stud_List
put arrayAdapter.notifyDataSetChanged(); in onPostExecute()
It is possible that sometime notifiDatasetChanged not works with custom adapter.
you can create custom method in your adapter like below :
public void refresh(ArrayList<HashMap<String, String>> list)
{
this.list=list; //replace this.list with your adapter list variable.
notifyDataSetChanged();
}
call it in onPostExecute()
arrayAdapter.refresh(stud_List);
Your asynctask runs asyncronously so when you call execute() on asynctask it will run in a parallel thread while the execution of main thread continues. So your notifydatasetchanged() is getting called even before your asynctask() is finished. So call notifyDataSetChanged() inside onPostExecute()

Android ListView Pull Down and Pull Up

I am new on Android Applications development. I want to know how to implement Pull down refresh and Pull up get more item from server in Listview.
How can I do it?
My Code get items from server is below.
private class DownloadJSONItems extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressbar
if (!prefs) {
progressBar.setVisibility(View.VISIBLE);
}
}
#Override
protected Void doInBackground(Void... params) {
// Create an array
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given URL address
jsonobject = JSONfunctions.getJSONfromURL("Server URL",latitude, longitude);
try {
// Locate the array name in JSON
jsonarray = jsonobject.getJSONArray("places");
for (int i = 0; i < jsonarray.length(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
jsonobject = jsonarray.getJSONObject(i);
double convertString = Double.parseDouble(jsonobject.getString("distance"));
double convertKMToMile = convertString * 0.6124;
String convertedValue = String.format("%.2f",convertKMToMile);
// Retrive JSON Objects
map.put("places_name", jsonobject.getString("places_name"));
map.put("distance", convertedValue);
map.put("places_icon", jsonobject.getString("places_icon"));
// Set the JSON Objects into the array
arraylist.add(map);
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
//Toast.makeText(getActivity(), getString(jsonarray.length()), 6000).show();
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(getActivity(), arraylist);
// Set the adapter to the ListView
listview.setAdapter(adapter);
// Close the progressbar
progressBar.setVisibility(View.GONE);
if (prefs) {
prefs = false;
}
}
}
Thank you.
There is a nice library for that https://github.com/Maxwin-z/XListView-Android
For Refresh:
#Override
public void onRefresh() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
start = ++refreshCnt;
items.clear();
geneItems();
// mAdapter.notifyDataSetChanged();
mAdapter = new ArrayAdapter<String>(XListViewActivity.this, R.layout.list_item, items);
mListView.setAdapter(mAdapter);
onLoad();
}
}, 2000);
}
For load more:
#Override
public void onLoadMore() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
geneItems();
mAdapter.notifyDataSetChanged();
onLoad();
}
}, 2000);
}

Toast in Asyntask is not showed properly

Toast is showed around of 2 times, and Json is returning fine 6 objects.
Idk if its problem of RunOnUiThread (I know that is not good for use in asyntask) or otherthing.
what other way can I use for my variable "mensaje" every time that for put a string in that I can show a Toat, maybe in OnPostExecute.
class asyncMensaje extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String user = params[0];
ArrayList<NameValuePair> envioDato = new ArrayList<NameValuePair>();
envioDato.add(new BasicNameValuePair("rut", user));
JSONArray jdata2 = post.getserverdata(envioDato, URL_connectFechas);
if (jdata2 != null && jdata2.length() > 0) {
JSONObject json_data; // creamos un objeto JSON
for (int i = 0; i < jdata2.length(); i++) {
try {
json_data = jdata2.getJSONObject(i);
mensaje = json_data.getString("mensaje");
Log.e("Info: ", "" + mensaje);
} catch (JSONException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), mensaje, Toast.LENGTH_LONG).show();
}
});
}
}
return null;
}
protected void onPostExecute(String result) {
}
}
The ideal solution in your case is to use onProgressUpdate together with sequencing of Toasts. Refer to this answer for doing the latter.
class asyncMensaje extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
//....
for (int i = 0; i < jdata2.length(); i++) {
//..
publishProgress(mensaje);
}
}
#Override
protected void onProgressUpdate(String... progress) {
//code for showing Toast
}
}
Use onPostExecute method for processing data after getting from webservice in doInBackground instead of using runOnUiThread in doInBackground which run on different Thread. do it as:
#Override
protected String doInBackground(String... params) {
String user = params[0];
ArrayList<NameValuePair> envioDato = new ArrayList<NameValuePair>();
envioDato.add(new BasicNameValuePair("rut", user));
JSONArray jdata2 = post.getserverdata(envioDato, URL_connectFechas);
return jdata2.toString();
}
#Override
protected void onPostExecute(String result) {
JSONArray jdata2=new JSONArray(result);
// parse JSONArray here and show Toast...
}

Android URL fetch and parse from sample - error

I'm trying a simple example : http://www.vogella.com/articles/AndroidJSON/article.html
But got an error .. Can anyone tell me why I get this error : http://puu.sh/1mGz1
use AsyncTask for making server request from UI Thread so change your code as:
///Your code...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//call readtwitterFeed() method here
String readtwitterFeed=readtwitterFeed();
return readtwitterFeed;
}
#Override
protected void onPostExecute(String result) {
try {
JSONArray jsonArray = new JSONArray(result);
Log.i(ParseJSON.class.getName(),
"Number of entries " + jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Log.i(ParseJSON.class.getName(), jsonObject.getString("text"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
You are trying to make data request on the main thread. Use AsyncTask to do it.
Or add this 2 line in the onCreate() method to bypass it.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
I recommend using asynctask though.

Categories

Resources