Szukałem wszędzie, próbując dowiedzieć się, dlaczego mój kod powodował problem. Mam GridView, który ma ArrayAdapter, który ściąga zdjęcia za pomocą AsyncTask. Widzę, że elementy są aktualizowane, ale kiedy próbuję zaktualizować adapter, GridView wydaje się nie aktualizować z nowym widokiem.GridView nie aktualizuje swoich widoków podrzędnych po tym, jak adapter otrzymuje nowe elementy.
Jest odpowiedni kod, który działa ...
private void fetchJsonResponse(String url) {
// Pass second argument as "null" for GET requests
JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET,
url + "&api_key=" + API_KEY,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray photos = response.getJSONArray("photos");
for(int i = 0; i < photos.length(); i++){
JSONObject object = photos.getJSONObject(i);
String url = object.getString("img_src");
//String id = object.getString("id");
list.add(new ImageItem(null, "Picture", url));
Log.i("Debug 2", url);
}
Log.i("Debug 2", list.get(0).toString());
if(gridViewAdapter != null){
gridViewAdapter.clear();
gridViewAdapter.addAll(list);
gridViewAdapter.notifyDataSetChanged();
gridView.invalidateViews();
} else {
gridViewAdapter = new GridViewAdapter(getActivity(), R.layout.gridview_item, list);
gridView.setAdapter(gridViewAdapter);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
});
/* Add your Requests to the RequestQueue to execute */
mRequestQueue.add(req);
}
private class MyAsyncTask extends AsyncTask<String, Void, Void> {
private ProgressDialog progressDialog;
private Context context;
public MyAsyncTask (Context context){
this.context = context;
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Contacting Rover...");
}
@Override
protected Void doInBackground(String... strings) {
fetchJsonResponse(strings[0]);
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(getActivity(), "In Pre Execute", Toast.LENGTH_SHORT).show();
progressDialog.show();
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
}
}
Ja naprawdę wdzięczni za każdą pomoc, jeśli to możliwe. Próbuję dostać aplikację przed nowymi latami :).
Może Jeśli możesz mi powiedzieć, dlaczego tak się dzieje, To nie spowoduje problemu ponownie, a inni zobaczą.
EDYCJA: Dodano nieco więcej kodu, który ma odświeżenie po dwukrotnym kliknięciu przycisku.
private void fetchJsonResponse(String url) {
// Pass second argument as "null" for GET requests
JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET,
url + "&api_key=" + API_KEY,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray photos = response.getJSONArray("photos");
list.clear();
for(int i = 0; i < photos.length(); i++){
JSONObject object = photos.getJSONObject(i);
String url = object.getString("img_src");
list.add(new ImageItem(null, "Picture", url));
Log.i("Debug 2", url);
}
Log.i("Debug 2", list.get(0).toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
});
/* Add your Requests to the RequestQueue to execute */
mRequestQueue.add(req);
}
private class MyAsyncTask extends AsyncTask<String, Void, Void> {
private ProgressDialog progressDialog;
private Context context;
public MyAsyncTask (Context context){
this.context = context;
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Contacting Rover...");
pictureAdapter = new PictureAdapter(getActivity(), list);
gridView.setAdapter(pictureAdapter);
}
@Override
protected Void doInBackground(String... strings) {
fetchJsonResponse(strings[0]);
return null;
}
@Override
protected void onPreExecute() {
progressDialog.show();
super.onPreExecute();
Toast.makeText(getActivity(), "In Pre Execute", Toast.LENGTH_SHORT).show();
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
pictureAdapter.updateItemList(list);
gridView.invalidate();
progressDialog.dismiss();
}
}
Adapter:
public class PictureAdapter extends BaseAdapter {
private ArrayList<ImageItem> items;
private Context context;
private TextView titleText;
private ImageView itemImage;
public PictureAdapter(Context context, ArrayList<ImageItem> items){
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = LayoutInflater.from(context).inflate(R.layout.gridview_item, parent, false);
titleText = (TextView) v.findViewById(R.id.text);
itemImage = (ImageView)v.findViewById(R.id.image);
titleText.setText(items.get(position).getTitle());
Picasso.with(context).load(items.get(position).getUrl()).fit().into(itemImage);
return v;
}
public void updateItemList(ArrayList<ImageItem> newItemList){
this.items = newItemList;
notifyDataSetChanged();
}
}
http://stackoverflow.com/questions/24874177/gridview-is-not-refreshing-view-after-data-changed?rq=1 może być przydatna – Redman
Czy otrzymujesz jakieś błędy? Chociaż nie jestem pewien, ale wydaje się, że próbujesz wykonać wywołania do adaptera i widoku na wątku non-ui. W jakim wątku wykonywany jest element responseListener? –
@Redman Dzięki! Przyjrzę się temu i zobaczę, czy mogę użyć ViewHolder. Wszystko pomaga! Bez błędów, widzę nawet adresy URL obrazów, więc pokazują, że są. Zakładam, że działa na wątku tła. To jest wywoływane w AsyncTask, który działa również w tle, ale nie? Bardzo dziękuję za pomoc! – SmiffyKmc