Динамическое изменение данных Adapter'a, добавленных с помощью HashMap

Рейтинг: 0Ответов: 1Опубликовано: 29.04.2015

Ситуация:

На главной Activity совершается поисковой запрос по REST API к серверу. Выполняется асинхронно. Если запрос успешен, то происходит его обработка в Callback.success. Там результаты запроса добавляются в HashMap, после чего сама HashMap добавляется (.add) в ArrayList. После завершения и добавления всех данных в ArrayList, создается SimpleAdapter с собственной разметкой, и в него добавляются данные из этого ArrayList. После чего ListView.setAdapter(SimpleAdapter).

Проблема:

Ответ от сервера содержит строковые данные, один из которых является URL на картинку. Следовательно, эту картинку надо загрузить. Для этого вызывается AsyncTask с загрузкой картинки. Так как выполнение, обработка и добавление текста в ArrayList происходит быстрее, чем загрузка картинок, то картинки в конечном итоге в Adapter (и соответственно в ListView) не попадают (т.е. drawable = null, так как на момент добавления (.put) в HashMap он ещё не инициализирован).

Вопрос

Можно ли как-то потом, в onPostExecute добавить в отображаемые элементы ListView загруженную картинку?

SearchResult.java

   private Drawable drawable;

   private void showResults(final int cityId) {
    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint(API.BASE_URL)
            .build();
    API service = restAdapter.create(API.class);
    service.getRoutes(cityId, new Callback<List<Route>>() {
        @Override
        public void success(List<Route> routes, Response response) {
            //В случае, если запрос к сервису был удачен, то происходит обработка
            if (routes.size() != 0) {   
                ArrayList<HashMap<String, Object>> resultList =
                        new ArrayList<HashMap<String, Object>>();
                HashMap<String, Object> hashMap;

                for (int i=0; i < routes.size(); i++) {                        
                    hashMap = new HashMap<>();
                    hashMap.put("ID", routes.get(i).getRouteId());
                    hashMap.put("TITLE", routes.get(i).getRouteTitle());
                    hashMap.put("DESCRIPTION", routes.get(i).getRouteDescription());
                    hashMap.put("THEME", routes.get(i).getThemes(0));

                    new DownloadImageTask().execute(routes.get(i).getImgUrl()) //запуск AsyncTask для загрузки картинки
                    hashMap.put("ICON", drawable);

                    resultList.add(hashMap);
                }
                SimpleAdapter simpleAdapter = new SimpleAdapter(getBaseContext(),
                        resultList, R.layout.route_fragment,
                        new String[]{"TITLE", "DESCRIPTION", "THEME", "ICON"},
                        new int[] {R.id.textViewRouteTitle, R.id.textViewRouteDescription,
                                R.id.textViewRouteThemes, R.id.imageViewRoutePicture});

                ListView listView = (ListView)findViewById(R.id.listView);
                listView.setAdapter(simpleAdapter); });
}}
    private class DownloadImageTask extends AsyncTask<String, Void, Drawable> {

    public DownloadImageTask() {
    }

    protected Drawable doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mIcon11 = null;
        Drawable testDraw = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mIcon11 = BitmapFactory.decodeStream(in);
            testDraw = new BitmapDrawable(getResources(), mIcon11);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return testDraw;
    }

    @Override
    protected void onPostExecute(Drawable result) {
        drawable = result; //результат записывается в глобальную переменную
    }
}
}

layout/route_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mainLayout">

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageViewRoutePicture"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:src="@drawable/hermitage" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="@string/route_title"
    android:id="@+id/textViewRouteTitle"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@+id/imageViewRoutePicture"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:paddingLeft="5dp" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:text="@string/route_description"
    android:id="@+id/textViewRouteDescription"
    android:layout_below="@+id/textViewRouteTitle"
    android:layout_toRightOf="@+id/imageViewRoutePicture"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_above="@+id/textViewRouteThemes"
    android:paddingLeft="5dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:text="@string/route_themes"
    android:id="@+id/textViewRouteThemes"
    android:layout_alignBottom="@+id/imageViewRoutePicture"
    android:layout_toRightOf="@+id/imageViewRoutePicture"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:paddingLeft="5dp" />
</RelativeLayout>

Ответы

▲ 2

Зачем вы вручную по урлу картинку загружаете? Воспользуйтесь предназначенными для этого библиотеками - Glide или ImageLoader

Там же есть пример для списка:

// For a list:
@Override
public View getView(int position, View recycled, ViewGroup container) {
    final ImageView myImageView;
    if (recycled == null) {
        myImageView = (ImageView) inflater.inflate(R.layout.my_image_view,
                container, false);
    } else {
        myImageView = (ImageView) recycled;
    }

    String url = myUrls.get(position);

    Glide.with(myFragment)
        .load(url)
        .centerCrop()
        .placeholder(R.drawable.loading_spinner)
        .crossFade()
        .into(myImageView);

    return myImageView;
}