在Android中滚动时从JSON加载图像

时间:2013-11-18 11:49:14

标签: java android json list hashmap

我正在创建一个应用程序,其中包含许多从JSON文件加载的产品。一切都很好,但我有一个小问题,我很难找到答案。只需单击一个按钮,我就可以从服务器上的JSON文件中获取所有数据(它包含一个URL值以获取产品的图片)。单击按钮时,我想立即移动到产品列表,只加载可见图像。相反,它需要大约8秒钟才能加载,并且它会预先加载所有图像。有人可以告诉我,我做错了什么?我在线阅读我应该使用类似的东西:imageLoader.DisplayImage(data [position],image);,但我使用的是Hashmap,而不仅仅是一个字符串。

这是我的代码,非常感谢任何帮助:

LazyAdapter

public class LazyAdapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader; 

    public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader=new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.size();
    }

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

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

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


        TextView brand = (TextView)vi.findViewById(R.id.brand); // title
        TextView name = (TextView)vi.findViewById(R.id.name); // artist name
        TextView price = (TextView)vi.findViewById(R.id.price); // duration
        TextView imgValue = (TextView)vi.findViewById(R.id.imgValue);
        //TextView rating = (TextView)vi.findViewById(R.id.rating); // rating
        ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image

        HashMap<String, String> products = new HashMap<String, String>();
        products = data.get(position);

        // Setting all values in listview
        brand.setText(products.get(CustomizedListView.TAG_BRAND));
        name.setText(products.get(CustomizedListView.TAG_NAME));
        price.setText("£" + products.get(CustomizedListView.TAG_MIN_GBP));
        imgValue.setText(products.get(CustomizedListView.TAG_IMG));
        imgValue.setVisibility(View.GONE);
        //rating.setText("Rating: " + song.get(CustomizedListView.TAG_RATING_NO) + "/5");
        imageLoader.DisplayImage("http://debenhams.scene7.com/is/image/Debenhams/" + imgValue.getText() + "?hei=440&op_usm=1.1,0.5,0,0", thumb_image);

        return vi;
    }
}

的ListView

public class CustomizedListView extends Activity {
    // All static variables
    static final String link = "https://dl.dropboxusercontent.com/u/142838353/productlist.json";
    // XML node keys
    static final String TAG_PRODUCTS = "Products";
    static final String TAG_PRODNUM = "prodnum";
    static final String TAG_BRAND = "brand";
    static final String TAG_NAME = "name"; // parent node
    static final String TAG_MIN_GBP = "minGBP";
    static final String TAG_IMG = "img";
    static final String TAG_RATING_NO = "rating_number";

    JSONArray products = null;
    ListView list;
    LazyAdapter adapter;

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

        // Hashmap for ListView
        ArrayList<HashMap<String, String>> productList = new ArrayList<HashMap<String, String>>();

        // Creating JSON Parser instance
        JSONParser jParser = new JSONParser();

        // getting JSON string from URL
        JSONObject json = jParser.getJSONFromUrl(link);

        try {

            // Getting Array of Contacts
            products = json.getJSONArray(TAG_PRODUCTS);

            // looping through All Contacts
            for(int i = 0; i < products.length(); i++){
                JSONObject c = products.getJSONObject(i);

                // Storing each json item in variable
//              String prodnum = c.getString(TAG_PRODNUM);
                String brand = c.getString(TAG_BRAND);
                String name = c.getString(TAG_NAME);
                String img = c.getString(TAG_IMG);
                String price = c.getString(TAG_MIN_GBP);
                //String ratingNo = c.getString(TAG_RATING_NO);

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

                // adding each child node to HashMap key => value
                map.put(TAG_MIN_GBP, price);
                map.put(TAG_BRAND, brand);
                map.put(TAG_NAME, name);
                map.put(TAG_IMG, img);
                //map.put(TAG_RATING_NO, ratingNo);

                // adding HashList to ArrayList
                productList.add(map);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }


        list=(ListView)findViewById(R.id.list);

        // Getting adapter by passing xml data ArrayList
        adapter=new LazyAdapter(this, productList);        
        list.setAdapter(adapter);


        // Click event for single list row
        list.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                String brand = ((TextView) view.findViewById(R.id.brand)).getText().toString();
                String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
                String imgValue = ((TextView) view.findViewById(R.id.imgValue)).getText().toString();
                String price = ((TextView) view.findViewById(R.id.price)).getText().toString();
                //String imgVal = ((ImageView) view.findViewById(R.id.list_image)).;
                //String imgVal = ((ImageView) view.findViewById(R.id.img)).getResources().toString();

                // Starting new intent
                Intent in = new Intent(getApplicationContext(), ProductActivity.class);
                in.putExtra(TAG_BRAND, brand);
                in.putExtra(TAG_NAME, name);
                in.putExtra(TAG_IMG, imgValue);
                in.putExtra(TAG_MIN_GBP, price);
                startActivity(in);
            }
        });     
    }

    @Override
    public void onDestroy()
    {
        list.setAdapter(null);
        super.onDestroy();
    }
}

ImageLoader的

public class ImageLoader {

    MemoryCache memoryCache=new MemoryCache();
    FileCache fileCache;
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    ExecutorService executorService;
    Handler handler=new Handler();//handler to display images in UI thread

    public ImageLoader(Context context){
        fileCache=new FileCache(context);
        executorService=Executors.newFixedThreadPool(5);
    }

    final int stub_id=R.drawable.default_image;
    public void DisplayImage(String url, ImageView imageView)
    {
        imageViews.put(imageView, url);
        Bitmap bitmap=memoryCache.get(url);
        if(bitmap!=null)
            imageView.setImageBitmap(bitmap);
        else
        {
            queuePhoto(url, imageView);
            imageView.setImageResource(stub_id);
        }
    }

    private void queuePhoto(String url, ImageView imageView)
    {
        PhotoToLoad p=new PhotoToLoad(url, imageView);
        executorService.submit(new PhotosLoader(p));
    }

    private Bitmap getBitmap(String url) 
    {
        File f=fileCache.getFile(url);

        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is=conn.getInputStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            conn.disconnect();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Throwable ex){
           ex.printStackTrace();
           if(ex instanceof OutOfMemoryError)
               memoryCache.clear();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            FileInputStream stream1=new FileInputStream(f);
            BitmapFactory.decodeStream(stream1,null,o);
            stream1.close();

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=256;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            FileInputStream stream2=new FileInputStream(f);
            Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
            stream2.close();
            return bitmap;
        } catch (FileNotFoundException e) {
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public PhotoToLoad(String u, ImageView i){
            url=u; 
            imageView=i;
        }
    }

    class PhotosLoader implements Runnable {
        PhotoToLoad photoToLoad;
        PhotosLoader(PhotoToLoad photoToLoad){
            this.photoToLoad=photoToLoad;
        }

        @Override
        public void run() {
            try{
                if(imageViewReused(photoToLoad))
                    return;
                Bitmap bmp=getBitmap(photoToLoad.url);
                memoryCache.put(photoToLoad.url, bmp);
                if(imageViewReused(photoToLoad))
                    return;
                BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
                handler.post(bd);
            }catch(Throwable th){
                th.printStackTrace();
            }
        }
    }

    boolean imageViewReused(PhotoToLoad photoToLoad){
        String tag=imageViews.get(photoToLoad.imageView);
        if(tag==null || !tag.equals(photoToLoad.url))
            return true;
        return false;
    }

    //Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        PhotoToLoad photoToLoad;
        public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
        public void run()
        {
            if(imageViewReused(photoToLoad))
                return;
            if(bitmap!=null)
                photoToLoad.imageView.setImageBitmap(bitmap);
            else
                photoToLoad.imageView.setImageResource(stub_id);
        }
    }

    public void clearCache() {
        memoryCache.clear();
        fileCache.clear();
    }

}

1 个答案:

答案 0 :(得分:0)

如果你不反对使用图书馆这样做,我在Universal Image Loader取得了很大的成功。这需要解决问题的复杂性,并且很容易设置。有一些问题from a while back与其他一些实现有一些讨论(我不确定它们是否有任何维护)。即使您不使用该库,它们的设计模式也可能是一个有用的起点。