Android: отображение изображения в режиме просмотра изображений с помощью SimpleAdapter

Я новый андроид, теперь я хочу отображать изображение с URL-адреса. Я использую просмотр изображений в списке. Я хочу добавить список изображений в каждую строку элемента списка. Я использовал SimpleAdapter, но изображение отображается пустым.

Вот основная деятельность:

package com.example.mysqltest;

    import java.util.ArrayList;
    import java.util.HashMap;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    import android.app.ListActivity;
    import android.app.ProgressDialog;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ListAdapter;
    import android.widget.ListView;
    import android.widget.SimpleAdapter;

    public class ReadComments extends ListActivity {

        // Progress Dialog
        private ProgressDialog pDialog;

        // testing on Emulator:
        private static final String READ_COMMENTS_URL = "http://192.168.30.198/test/webservice/comments.php";


        // JSON IDS:
        private static final String TAG_SUCCESS = "success";
        private static final String TAG_TITLE = "title";
        private static final String TAG_POSTS = "posts";
        private static final String TAG_POST_ID = "post_id";
        private static final String TAG_USERNAME = "username";
        private static final String TAG_MESSAGE = "message";
        private static final String TAG_IMAGE = "image";


        // An array of all of our comments
        private JSONArray mComments = null;
        // manages all of our comments in a list.
        private ArrayList<HashMap<String, String>> mCommentList;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // note that use read_comments.xml instead of our single_post.xml
            setContentView(R.layout.read_comments);
        }

        @Override
        protected void onResume() {
            // TODO Auto-generated method stub
            super.onResume();
            // loading the comments via AsyncTask
            new LoadComments().execute();
        }

        public void addComment(View v) {
            Intent i = new Intent(ReadComments.this, AddComment.class);
            startActivity(i);
        }

        /**
         * Retrieves recent post data from the server.
         */
        public void updateJSONdata() {
            mCommentList = new ArrayList<HashMap<String, String>>();

            JSONParser jParser = new JSONParser();      
            JSONObject json = jParser.getJSONFromUrl(READ_COMMENTS_URL);

            try {
                mComments = json.getJSONArray(TAG_POSTS);

                for (int i = 0; i < mComments.length(); i++) {
                    JSONObject c = mComments.getJSONObject(i);

                    // gets the content of each tag
                    String title = c.getString(TAG_TITLE);
                    String content = c.getString(TAG_MESSAGE);
                    String username = c.getString(TAG_USERNAME);
                    String image = c.getString(TAG_IMAGE);

                    // creating new HashMap
                    HashMap<String, String> map = new HashMap<String, String>();

                    map.put(TAG_TITLE, title);
                    map.put(TAG_MESSAGE, content);
                    map.put(TAG_USERNAME, username);
                    map.put(TAG_IMAGE, image);

                    // adding HashList to ArrayList
                    mCommentList.add(map);
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        /**
         * Inserts the parsed data into the listview.
         */
        private void updateList() { 
            ListAdapter adapter = new SimpleAdapter(this, mCommentList,
                    R.layout.single_post, new String[] { TAG_TITLE, TAG_MESSAGE,
                            TAG_USERNAME,TAG_IMAGE }, new int[] { R.id.title, R.id.message,
                            R.id.username, R.id.imageView1 });

            // I shouldn't have to comment on this one:
            setListAdapter(adapter);    

            ListView lv = getListView();    
            lv.setOnItemClickListener(new OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                        int position, long id) {}
            });
        }

        public class LoadComments extends AsyncTask<Void, Void, Boolean> {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                pDialog = new ProgressDialog(ReadComments.this);
                pDialog.setMessage("Loading Comments...");
                pDialog.setIndeterminate(false);
                pDialog.setCancelable(true);
                pDialog.show();
            }

            @Override
            protected Boolean doInBackground(Void... arg0) {
                updateJSONdata();
                return null;

            }

            @Override
            protected void onPostExecute(Boolean result) {
                super.onPostExecute(result);
                pDialog.dismiss();
                updateList();
            }
        }
    }

person Vuthy Sok    schedule 02.06.2014    source источник
comment
SimpleAdapter.setViewImage работает с системными ресурсами, а не с сетевыми. Вам необходимо загрузить сетевое изображение и явно установить растровое изображение в ImageView. Вы можете попробовать этот ответ.   -  person Manish Mulimani    schedule 04.06.2014
comment
Спасибо за ваш комментарий. не могли бы вы мне помочь, как применить setViewImage в моем коде?   -  person Vuthy Sok    schedule 04.06.2014
comment
Привет, @VuthySok, ты там?   -  person PankajSharma    schedule 09.06.2014


Ответы (7)


Хорошо. Итак, я предполагаю, что вы настаиваете на использовании SimpleAdapter. Проблем нет, проблема решена, просто следуйте инструкциям:

Сначала давайте создадим наш собственный row.xml для нашего ListView, который будет состоять только из одного _3 _. (Вы можете добавить к нему все, что захотите позже, но теперь я предполагаю, что вы хотите загрузить только ImageView )

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

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="5dp"
        android:src="@drawable/ic_launcher" />


</RelativeLayout>

Во-вторых, давайте создадим наш собственный SimpleAdapter

package com.example.helpstack;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SimpleAdapter;

public class MySimpleAdapter extends SimpleAdapter {
    private Context mContext;
    public LayoutInflater inflater = null;

    public MySimpleAdapter(Context context,
            List<? extends Map<String, ?>> data, int resource, String[] from,
            int[] to) {
        super(context, data, resource, from, to);
        mContext = context;
        inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        if (convertView == null)
            vi = inflater.inflate(R.layout.row, null);

        HashMap<String, Object> data = (HashMap<String, Object>) getItem(position);

        new DownloadTask((ImageView) vi.findViewById(R.id.imageView1))
                .execute((String) data.get("uri"));

        return vi;
    }

}

В-третьих, давайте создадим наш DownloadTask, этот класс загрузит изображение:

package com.example.helpstack;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

public class DownloadTask extends AsyncTask<String, Void, Boolean> {
    ImageView v;
    String url;
    Bitmap bm;

    public DownloadTask(ImageView v) {
        this.v = v;
    }

    @Override
    protected Boolean doInBackground(String... params) {
        url = params[0];
        bm = loadBitmap(url);
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        v.setImageBitmap(bm);
    }

    public static Bitmap loadBitmap(String url) {
        try {
            URL newurl = new URL(url);
            Bitmap b = BitmapFactory.decodeStream(newurl.openConnection()
                    .getInputStream());
            return b;
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

Теперь DownloadTask используется внутри getView () в SimpleAdapter

В-четвертых, давайте запустим наш замечательный небольшой проект из нашего MainActivity.java.

package com.example.helpstack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {
    ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.listView1);
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("uri",
                "http://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Wiktionary_small.svg/350px-Wiktionary_small.svg.png");
        //here u can add as many uri as u want
        data.add(map);
        MySimpleAdapter adapter = new MySimpleAdapter(MainActivity.this, data,
                R.layout.row, new String[] {}, new int[] {});
        lv.setAdapter(adapter);
    }
}
person Alan Deep    schedule 06.06.2014
comment
Я следил за вашим кодом, но всегда закрываю приложение при запуске - person Vuthy Sok; 09.06.2014
comment
Вы добавили разрешение в Интернет в файл манифеста? Он не должен закрываться. Попробуй добавить разрешение, если не получится, пришлю свой образец. Но я предлагаю вам рассказать нам, какие ошибки возникают в logcat. - person Alan Deep; 10.06.2014
comment
да, я добавил разрешение ‹использует-разрешение android: name = android.permission.INTERNET /›. Я не уверен, в чем проблема, но при открытии приложения всегда отображается сообщение. К сожалению, мой SimpleAdapter остановился. - person Vuthy Sok; 10.06.2014
comment
Это общий проект: docs.google.com/ - person Alan Deep; 11.06.2014

Вы можете использовать любую библиотеку кеширования изображений. Пример, Picasa, Универсальный загрузчик изображений ..

Вы можете кэшировать изображения из URL-адреса, а затем использовать изображения в своем приложении.

Вы можете найти библиотеки по следующим ссылкам

http://square.github.io/picasso/ и https://github.com/nostra13/Android-Universal-Image-Loader

person Sripathi    schedule 10.06.2014

Вы можете использовать несколько потоков для загрузки и декодирования растрового изображения. Следите за этим веб-сайтом и попробуйте узнать, как разработчик Android использует исполнитель пула потоков для выполнения другого изображения в потоке. http://developer.android.com/training/multiple-threads/create-threadpool.html

person mcd    schedule 09.06.2014

1) Чтобы установить Uri изображения в ImageView, вы можете использовать ViewBinder
Вы должны реализовать абстрактный класс и переопределить setViewValue

2) Вы можете использовать Picasso для загрузки изображений в фоновый поток и их кеширования. Метод setViewValue будет выглядеть так:

boolean setViewValue (View view, Object data, String textRepresentation) {
  if(view.getId() == R.id.imageView1) {
    Picasso.with(view.getContext()).load(textRepresentation).into((ImageView) view);
    return true;
  }
  return false;
}

Вы возвращаете true, если хотите позаботиться о привязке. Вы возвращаете false для поведения по умолчанию.

3) Настройте свой adapter на использование ViewBinder, позвонив adapter.setViewBinder(ViewBinder);

person LordRaydenMK    schedule 10.06.2014

на данный момент я предлагаю вам:
1. загрузить изображение с URL-адреса
2. сохранить его как доступное для рисования в хранилище
3. установить этот доступный для рисования для изображения src из imageview
(я не видел, чтобы вы выполнили эту часть работы из своего кода ...)

person shanwu    schedule 02.06.2014

Это руководство является лучшим примером для синтаксического анализа изображения с помощью синтаксического анализа json и отображения его в виде списка: http://www.androidbegin.com/tutorial/android-json-parse-images-and-texts-tutorial/

Несколько других:

http://imagelistviewdynamic.blogspot.in/2012/12/image-parsed-from-json-using-async-into.html

http://www.java2s.com/Open-Source/Android_Free_Code/JSON/Download_Free_code_Android_JSON_Parse_Images_and_Texts_Tutorial.htm

person kgandroid    schedule 04.06.2014

Я предлагаю вам использовать Universal Image Loader, он использует асинхронную загрузку, кеширование и отображение изображений. , там вы можете найти примеры, как это реализовать. После того, как вы это сделаете, вам не нужно беспокоиться о количестве изображений или их размере.

Если вы загрузите проект, вы найдете этот пример, который выполняет всю работу, которую вы хотите:

/**
 * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 */
public class ImageListActivity extends AbsListViewBaseActivity {

    DisplayImageOptions options;

    String[] imageUrls;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ac_image_list);

            // here you get a String array with images URL
        Bundle bundle = getIntent().getExtras();
        imageUrls = bundle.getStringArray(Extra.IMAGES);

        options = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.ic_stub)
            .showImageForEmptyUri(R.drawable.ic_empty)
            .showImageOnFail(R.drawable.ic_error)
            .cacheInMemory(true)
            .cacheOnDisc(true)
            .considerExifParams(true)
            .displayer(new RoundedBitmapDisplayer(20))
            .build();

        listView = (ListView) findViewById(android.R.id.list);
        ((ListView) listView).setAdapter(new ItemAdapter());
        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                startImagePagerActivity(position);
            }
        });
    }

    @Override
    public void onBackPressed() {
        AnimateFirstDisplayListener.displayedImages.clear();
        super.onBackPressed();
    }
    // it gets the position of listView and opens that image in a new Activity
    private void startImagePagerActivity(int position) {
        Intent intent = new Intent(this, ImagePagerActivity.class);
        intent.putExtra(Extra.IMAGES, imageUrls);
        intent.putExtra(Extra.IMAGE_POSITION, position);
        startActivity(intent);
    }

    class ItemAdapter extends BaseAdapter {

        private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();

        private class ViewHolder {
            public TextView text;
            public ImageView image;
        }

        @Override
        public int getCount() {
            return imageUrls.length;
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = convertView;
            final ViewHolder holder;
            if (convertView == null) {
                view = getLayoutInflater().inflate(R.layout.item_list_image, parent, false);
                holder = new ViewHolder();
                holder.text = (TextView) view.findViewById(R.id.text);
                holder.image = (ImageView) view.findViewById(R.id.image);
                view.setTag(holder);
            } else {
                holder = (ViewHolder) view.getTag();
            }

            holder.text.setText("Item " + (position + 1));
                    // here is the place where is loaded the image using Universal ImageLoader , imageUrls[position] is a list of images URL
            imageLoader.displayImage(imageUrls[position], holder.image, options, animateFirstListener);

            return view;
        }
    }

    private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {

        static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            if (loadedImage != null) {
                ImageView imageView = (ImageView) view;
                boolean firstDisplay = !displayedImages.contains(imageUri);
                if (firstDisplay) {
                    FadeInBitmapDisplayer.animate(imageView, 500);
                    displayedImages.add(imageUri);
                }
            }
        }
    }
}
person Ultimo_m    schedule 06.06.2014