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
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);
}
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()
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 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...
}
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.