У меня есть ListView, заполненный из json и использующий пользовательский адаптер.
Это мой сокращенный код в ZoznamActivity:
public class Zoznam extends AppCompatActivity{
private ArrayList<Actors> actorsList;
private ActorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_filter);
final ListView lv = findViewById(R.id.listView1);
actorsList = new ArrayList<>();
adapter = new ActorAdapter(this, "Zoznam", actorsList);
lv.setAdapter(adapter);adapter.notifyDataSetChanged();
new GetContacts(Zoznam.this).execute("all","all");
private static class GetContacts extends AsyncTask<String, Void, String> {
ProgressDialog dialog;
private final WeakReference<Zoznam> activityReference;
GetContacts(Zoznam context) {
activityReference = new WeakReference<>(context);
}
@Override
protected void onPreExecute() {
Zoznam activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
super.onPreExecute();
dialog = new ProgressDialog(activity);
dialog.setMessage(activity.getResources().getString(R.string.Loading));
dialog.setTitle(activity.getResources().getString(R.string.connecting));
dialog.show();
dialog.setCancelable(false);
}
@Override
protected String doInBackground(String... sText1) {final Zoznam activity = activityReference.get();
HttpHandler sh = new HttpHandler();
String url = "URL";
String jsonStr = sh.makeServiceCall(url);
if (jsonStr != null) {
try {JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray actors = jsonObj.getJSONArray("result");
for (int i = 0; i < actors.length(); i++) {
JSONObject c = actors.getJSONObject(i);
Actors actor = new Actors();
actor.setLetter(c.getString("letter"));
actor.setNazov(c.getString("nazov"));
actor.setThumb(c.getString("thumb"));
activityReference.get().actorsList.add(actor);
}
} catch (final JSONException e) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity,
R.string.Nodata,
Toast.LENGTH_LONG).show();
}
}); }
return jsonStr;
} else {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity,
R.string.Network,
Toast.LENGTH_LONG).show();
}
});
return null;
}
}
protected void onPostExecute(String result) {
Zoznam activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
dialog.dismiss();
activity.adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
protected void onResume() {
super.onResume();
adapter.notifyDataSetChanged();
}
Проблема в том, что в отчетах о сбоях я обнаружил эту ошибку:
Содержимое адаптера изменилось, но ListView не получил уведомление. Убедитесь, что содержимое вашего адаптера не изменено из фонового потока, а только из потока пользовательского интерфейса. Убедитесь, что ваш адаптер вызывает notifyDataSetChanged () при изменении его содержимого.
Однако это произошло только один раз для одного устройства, но я бы хотел это исправить.
Я уже читал об этом, но у меня все еще нет решения. Как вы можете видеть в моем коде, я вызываю notifyDataSetChanged () также onResume и onPostExecute, поэтому не уверен, куда мне поместить это в другом месте.
Я думаю, что мне нужно использовать activity.runOnUiThread (new Runnable ())где-то после цикла for из json, где я добавляю элементы в arraylist, но не уверен, как это сделать, и если это решит проблему.
Мое последнее обновление кода:
for (int i = 0; i < actors.length(); i++) {
JSONObject c = actors.getJSONObject(i);
final Actors actor = new Actors();
actor.setLetter(c.getString("letter"));
actor.setNazov(c.getString("nazov"));
actor.setThumb(c.getString("thumb"));
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activityReference.get().actorsList.add(actor);
activity.adapter.notifyDataSetChanged();
}
});
}