如何在gridview中添加lazyloader?

时间:2013-10-28 04:39:29

标签: android android-gridview

public class NewMovie extends Activity     {
    GridView lv;
    Vibrator vibrator;
    SimpleAdapter adapter ;
    Button b;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        enter code heresuper.onCreate(savedInstanceState);
        Log.i("Category", MainActivity.movie_Category);
        setContentView(R.layout.new_movie);
        LayoutInflater li = getLayoutInflater();
        View layout = li.inflate(R.layout.customtoast, (ViewGroup)              findViewById(R.id.custom_toast_layout));
        Toast toast = new Toast(getApplicationContext());
        toast.setDuration(Toast.LENGTH_LONG);
        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
        toast.setView(layout);
        toast.show();
        vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
        lv=(GridView)findViewById(R.id.grid_view);
        b=(Button)findViewById(R.id.profile_button);
        // URL to the JSON data         
        String strUrl = "http://vaibhavtech.com/work/android/movie_list.php?                                   category="+MainActivity.movie_Category+"&sub_category=new";
        // Creating a new non-ui thread task to download json data 
        DownloadTask downloadTask = new DownloadTask();
        // Starting the download processt
        downloadTask.execute(strUrl);

        // Getting a reference to ListView of activity_main
        lv.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long     arg3) {
                // // TODO Auto-generated method stub
                vibrator.vibrate(40);
                LayoutInflater inflater=getLayoutInflater();
                View view=inflater.inflate(R.layout.customtoast, (ViewGroup)findViewById(R.id.custom_toast_layout));
                Toast toast=new Toast(getApplicationContext());
                toast.setDuration(Toast.LENGTH_LONG);
                toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
                toast.setView(view);
                toast.show();
                MainActivity.movie_Id= ((TextView)arg1.findViewById(R.id.tv_girdview_content_id)).getText().toString();
                Log.i("Name is", MainActivity.movie_Id);

                startActivity(new Intent(NewMovie.this,MovieDescription.class));
            }
        });
    }
    /** A method to download json data from url */
    private String downloadUrl(String strUrl) throws IOException{
        String data = "";
        InputStream iStream = null;

        try{
            URL url = new URL(strUrl);

            // Creating an http connection to communicate with url 
            HttpURLConnection urlConnection = (HttpURLConnection)                    url.openConnection();

            // Connecting to url 
            urlConnection.connect();

            // Reading data from url 
            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

            StringBuffer sb  = new StringBuffer();

            String line = "";
            while( ( line = br.readLine())  != null){
                sb.append(line);
            }

            data = sb.toString();

            br.close();

        }catch(Exception e){
            Log.d("Exception while downloading url", e.toString());
        }finally{
            iStream.close();
        }

        return data;
    }
    /** AsyncTask to download json data */
    private class DownloadTask extends AsyncTask<String, Integer, String>{
        String data = null;
        @Override
        protected String doInBackground(String... url) {
            try{
                data = downloadUrl(url[0]);

            }catch(Exception e){
                Log.d("Background Task",e.toString());
            }
            return data;
        }

        @Override
        protected void onPostExecute(String result) {

            // The parsing of the xml data is done in a non-ui thread 
            ListViewLoaderTask listViewLoaderTask = new           ListViewLoaderTask();

            // Start parsing xml data
            listViewLoaderTask.execute(result);                        
        }
    }

    /** AsyncTask to parse json data and load ListView */
    private class ListViewLoaderTask extends AsyncTask<String, Void, SimpleAdapter>{

        JSONObject jObject;
        // Doing the parsing of xml data in a non-ui thread 
        @Override
        protected SimpleAdapter doInBackground(String... strJson) {
            try{
                jObject = new JSONObject(strJson[0]);
                MovieParser countryJsonParser = new MovieParser();
                countryJsonParser.parse(jObject);
            }catch(Exception e){
                Log.d("JSON Exception1",e.toString());
            }

            // Instantiating json parser class
            MovieParser countryJsonParser = new MovieParser();

            // A list object to store the parsed countries list
            List<HashMap<String, Object>> countries = null;

            try{
                // Getting the parsed data as a List construct
                countries = countryJsonParser.parse(jObject);
            }catch(Exception e){
                Log.d("Exception",e.toString());
            }          

            // Keys used in Hashmap 
            String[] from = { "image","id","year","duration","name"};

            // Ids of views in listview_layout
            //  int[] to = { R.id.iv_radio_data_image,R.id.tv_radio_data_id,R.id.tv_radio_data_like,R.id.tv_radio_data_rating,R.id.tv_radio_data_listner,R.id.tv_radio_data_radio_url,R.id.tv_radio_data_name};
            int[] to = { R.id.iv_girdview_content_image,R.id.tv_girdview_content_id,R.id.tv_girdview_content_like,R.id.tv_girdview_content_listner,R.id.tv_girdview_content_name};
            // Instantiating an adapter to store each items
            // R.layout.listview_layout defines the layout of each item         
            adapter = new SimpleAdapter(getBaseContext(), countries, R.layout.grid_view_content, from, to);  

            return adapter;
            //  lv.setAdapter(new ListAdapter(getApplicationContext()));
        }

        /** Invoked by the Android on "doInBackground" is executed */
        @Override
        protected void onPostExecute(SimpleAdapter adapter) {

            // Setting adapter for the listview
            lv.setAdapter(adapter);

            for(int i=0;i<adapter.getCount();i++){
                HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(i);
                String imgUrl = (String) hm.get("flag_path");
                ImageLoaderTask imageLoaderTask = new ImageLoaderTask();

                HashMap<String, Object> hmDownload = new HashMap<String, Object>();
                hm.put("flag_path",imgUrl);
                hm.put("position", i);

                // Starting ImageLoaderTask to download and populate image in the listview 
                imageLoaderTask.execute(hm);

            }

            //}     

        }

        /** AsyncTask to download and load an image in ListView */
        private class ImageLoaderTask extends AsyncTask<HashMap<String, Object>, Void, HashMap<String, Object>>{

            @Override
            protected HashMap<String, Object> doInBackground(HashMap<String, Object>... hm) {

                InputStream iStream=null;
                String imgUrl = (String) hm[0].get("flag_path");
                int position = (Integer) hm[0].get("position");

                URL url;
                try {
                    url = new URL(imgUrl);

                    // Creating an http connection to communicate with url
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

                    // Connecting to url                
                    urlConnection.connect();

                    // Reading data from url 
                    iStream = urlConnection.getInputStream();

                    // Getting Caching directory 
                    File cacheDirectory = getBaseContext().getCacheDir();

                    // Temporary file to store the downloaded image 
                    File tmpFile = new File(cacheDirectory.getPath() + "/wpta_"+position+".png");               

                    // The FileOutputStream to the temporary file
                    FileOutputStream fOutStream = new FileOutputStream(tmpFile);

                    // Creating a bitmap from the downloaded inputstream
                    Bitmap b = BitmapFactory.decodeStream(iStream);             

                    // Writing the bitmap to the temporary file as png file
                    b.compress(Bitmap.CompressFormat.PNG,100, fOutStream);              

                    // Flush the FileOutputStream
                    fOutStream.flush();

                    //Close the FileOutputStream
                    fOutStream.close();             

                    // Create a hashmap object to store image path and its position in the listview
                    HashMap<String, Object> hmBitmap = new HashMap<String, Object>();

                    // Storing the path to the temporary image file
                    hmBitmap.put("image",tmpFile.getPath());

                    // Storing the position of the image in the listview
                    hmBitmap.put("position",position);              

                    // Returning the HashMap object containing the image path and position
                    return hmBitmap;                


                }catch (Exception e) {              
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(HashMap<String, Object> result) {
                // Getting the path to the downloaded image
                String path = (String) result.get("image");         

                // Getting the position of the downloaded image
                int position = (Integer) result.get("position");

                // Getting adapter of the listview
                adapter = (SimpleAdapter ) lv.getAdapter();

                // Getting the hashmap object at the specified position of the listview
                HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(position);   

                // Overwriting the existing path in the adapter 
                hm.put("image",path);

                //lv.invalidateViews();
                adapter.notifyDataSetChanged(); 

            }
        }

    }
}

我是新手。我不知道在我的应用程序中使用lazyloader代码的位置。

我想在我使用lazyloader的应用程序中使用GridView。我想在gridview中显示加载所有项目的项目。

3 个答案:

答案 0 :(得分:0)

使用以下代码为我工作。

Main.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.GridView;

public class Main extends Activity {
    String mImagesPath;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mImagesPath = this.getFilesDir().getParent() + "/images/";
        createImagesDir(mImagesPath);
        copyImagesToStorage();
        loadGridView();
    }

    /**
     * Method handles the logic for setting the adapter for the gridview
     */
    private void loadGridView(){

        GridView lLazyGrid = (GridView) this.findViewById(R.id.gridview);
        try {
            LazyImageAdapter lLazyAdapter = new LazyImageAdapter(this.getApplicationContext(),
                    null,
                    mImagesPath);
            lLazyGrid.setAdapter(lLazyAdapter);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * Copy images from assets to storage
     */
    private void copyImagesToStorage(){
        AssetManager lAssetManager = getAssets();
        String[] lFiles = null;
        String lTag = "copyImageFail";

        try {
            // get all of the files in the assets directory
            lFiles = lAssetManager.list("");
        } catch (IOException e) {
            Log.e(lTag, e.getMessage());
        }


        for(int i=0; i<lFiles.length; i++) {
            // We have a file to copy


            try {

                // copy the file
                copyFile(lFiles[i], mImagesPath + lFiles[i]);
            } catch(Exception e) {
                Log.e(lTag, e.getMessage());
            }       
        }
    }

    /**
     * Method copies the contents of one stream to another
     * @param aIn stream to copy from
     * @param aOut stream to copy to
     * @throws IOException
     */
    private void copyFile(String aIn, String aOut) throws IOException {
        byte[] lBuffer = new byte[1024];
        int lRead;
        final int lOffset = 0;

        // create an in and out stream
        InputStream lIn = getAssets().open(aIn);
        OutputStream lOut = new FileOutputStream(aOut);

        // Copy contents while there is data
        while((lRead = lIn.read(lBuffer)) != -1){
          lOut.write(lBuffer, lOffset, lRead);
        }

        // clean up after our streams
        lIn.close();
        lIn = null;
        lOut.flush();
        lOut.close();
        lOut = null;
    }

    /**
     * Create the directory specified at aPath if it does not exist
     * @param aPath directory to check for and create
     */
    private void createImagesDir(String aPath){
        File lDir = new File(aPath);
        if(!lDir.exists()){
            lDir.mkdir();
        }
    }
}

LazyImageAdapter.java

import java.io.File;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.ViewSwitcher;

import com.bacaj.lazygridview.ImageLoader.ImageLoadListener;

public class LazyImageAdapter extends BaseAdapter implements ImageLoadListener {

    private static final int PROGRESSBARINDEX = 0;
    private static final int IMAGEVIEWINDEX = 1;


    private Context mContext = null;
    private OnClickListener mItemClickListener;
    private Handler mHandler;
    private ImageLoader mImageLoader = null;
    private File mDirectory;

    /**
     * Lazy loading image adapter
     * @param aContext
     * @param lClickListener click listener to attach to each item
     * @param lPath the path where the images are located
     * @throws Exception when path can't be read from or is not a valid directory
     */
    public LazyImageAdapter(
            Context aContext,
            OnClickListener lClickListener,
            String lPath
        ) throws Exception {

        mContext = aContext;
        mItemClickListener = lClickListener;
        mDirectory = new File(lPath);

        // Do some error checking
        if(!mDirectory.canRead()){
            throw new Exception("Can't read this path");
        }
        else if(!mDirectory.isDirectory()){
            throw new Exception("Path is a not a directory");
        }

        mImageLoader = new ImageLoader(this);
        mImageLoader.start();
        mHandler = new Handler();

    }

    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        super.finalize();

        // stop the thread we started
        mImageLoader.stopThread();
    }

    public int getCount() {
        return mDirectory.listFiles().length;
    }

    public Object getItem(int aPosition) {
        String lPath = null;
        File []lFiles = mDirectory.listFiles();
        if(aPosition < lFiles.length){
            lPath = mDirectory.listFiles()[aPosition].getAbsolutePath();
        }

        return lPath;
    }

    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return 0;
    }

    public View getView(final int aPosition, View aConvertView, ViewGroup parent) {
        final ViewSwitcher lViewSwitcher;
        String lPath = (String)getItem(aPosition);

        // logic for conserving resources see google video on making your ui fast
        // and responsive
        if (null == aConvertView) {
            lViewSwitcher = new ViewSwitcher(mContext);
            lViewSwitcher.setPadding(8, 8, 8, 8);

            ProgressBar lProgress = new ProgressBar(mContext);
            lProgress.setLayoutParams(new ViewSwitcher.LayoutParams(80, 80));
            lViewSwitcher.addView(lProgress);
            ImageView lImage = new ImageView(mContext);
            lImage.setLayoutParams(new ViewSwitcher.LayoutParams(100, 100));

            lViewSwitcher.addView(lImage);

            // attach the onclick listener
            lViewSwitcher.setOnClickListener(mItemClickListener);

        } else {
            lViewSwitcher = (ViewSwitcher) aConvertView;
        }


        ViewTagInformation lTagHolder = (ViewTagInformation) lViewSwitcher
                .getTag();

        if (lTagHolder == null || 
            !lTagHolder.aImagePath.equals(lPath)) {
            // The Tagholder is null meaning this is a first time load
            // or this view is being recycled with a different image

            // Create a ViewTag to store information for later
            ViewTagInformation lNewTag = new ViewTagInformation();
            lNewTag.aImagePath = lPath;
            lViewSwitcher.setTag(lNewTag);

            // Grab the image view
            // Have the progress bar display
            // Then queue the image loading
            ImageView lImageView = (ImageView) lViewSwitcher.getChildAt(1);
            lViewSwitcher.setDisplayedChild(PROGRESSBARINDEX);
            mImageLoader.queueImageLoad(lPath, lImageView, lViewSwitcher);


        }

        return lViewSwitcher;
    }


    public void handleImageLoaded(
            final ViewSwitcher aViewSwitcher,
            final ImageView aImageView, 
            final Bitmap aBitmap) {

        // The enqueue the following in the UI thread
        mHandler.post(new Runnable() {
            public void run() {

                // set the bitmap in the ImageView
                aImageView.setImageBitmap(aBitmap);

                // explicitly tell the view switcher to show the second view
                aViewSwitcher.setDisplayedChild(IMAGEVIEWINDEX);
            }
        });

    }


}

/**
 *  View holder pattern as described in google sample code
 *  we may want to add more attributes to this if the path was
 *  say being stored in a sqlite database
 * @author bacaj
 */
class ViewTagInformation {
    String aImagePath;
}

ImageLoader.java

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ViewSwitcher;

public class ImageLoader extends Thread {

    public interface ImageLoadListener {

        void handleImageLoaded(ViewSwitcher aViewSwitcher, ImageView aImageView, Bitmap aBitmap);
    }

    private static final String TAG = ImageLoader.class.getSimpleName();
    ImageLoadListener mListener = null;
    private Handler handler;

    /**
     * Image loader takes an object that extends ImageLoadListener
     * @param lListener
     */
    ImageLoader(ImageLoadListener lListener){
        mListener = lListener;
    }

    @Override
    public void run() {
        try {

            // preparing a looper on current thread         
            // the current thread is being detected implicitly
            Looper.prepare();

            // Looper gets attached to the current thread by default
            handler = new Handler();

            Looper.loop();
            // Thread will start

        } catch (Throwable t) {
            Log.e(TAG, "ImageLoader halted due to a error: ", t);
        } 
    }

    /**
     * Method stops the looper and thus the thread
     */
    public synchronized void stopThread() {

        // Use the handler to schedule a quit on the looper
        handler.post(new Runnable() {

            public void run() {
                // This runs on the ImageLoader thread
                Log.i(TAG, "DownloadThread loop quitting by request");

                Looper.myLooper().quit();
            }
        });
    }

    /**
     * Method queues the image at path to load
     * Note that the actual loading takes place in the UI thread
     * the ImageView and ViewSwitcher are just references for the
     * UI thread.
     * @param aPath      - Path where the bitmap is located to load
     * @param aImageView - The ImageView the UI thread will load 
     * @param aViewSwitcher - The ViewSwitcher that needs to display the imageview
     */
    public synchronized void queueImageLoad(
            final String aPath, 
            final ImageView aImageView, 
            final ViewSwitcher aViewSwitcher) {

        // Wrap DownloadTask into another Runnable to track the statistics
        handler.post(new Runnable() {
            public void run() {
                try {

                    synchronized (aImageView){
                        // make sure this thread is the only one performing activities on
                        // this imageview
                        BitmapFactory.Options lOptions = new BitmapFactory.Options();
                        lOptions.inSampleSize = 1;
                        Bitmap lBitmap = BitmapFactory.decodeFile(aPath, lOptions);
                        //aImage.setImageBitmap(lBitmap);

                        // Load the image here
                        signalUI(aViewSwitcher, aImageView, lBitmap);
                    }
                } 
                catch(Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Method is called when the bitmap is loaded.  The UI thread adds the bitmap to the imageview.
     * @param aViewSwitcher - The ViewSwitcher that needs to display the imageview
     * @param aImageView - The ImageView the UI thread will load 
     * @param aImage - The Bitmap that gets loaded into the ImageView
     */
    private void signalUI(
            ViewSwitcher aViewSwitcher, 
            ImageView aImageView, 
            Bitmap aImage){

        if(mListener != null){
            // we have an object that implements ImageLoadListener

            mListener.handleImageLoaded(aViewSwitcher, aImageView, aImage);
        }
    }

}

希望它可以帮助你。

答案 1 :(得分:0)

答案 2 :(得分:0)

            // Setting adapter for the listview
        lv.setAdapter(adapter);

        for(int i=0;i<adapter.getCount();i++){
            HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(i);
            String imgUrl = (String) hm.get("flag_path");
            ImageLoaderTask imageLoaderTask = new ImageLoaderTask();

            HashMap<String, Object> hmDownload = new HashMap<String, Object>();
            hm.put("flag_path",imgUrl);
            hm.put("position", i);

            // Starting ImageLoaderTask to download and populate image in the listview 
            imageLoaderTask.execute(hm);

        }

这个代码就是问题所在,你正在启动数百个AsynTasks(线程),这会导致你提到的问题。

我建议您使用自定义网格适配器和任何其他Lazy加载库进行图像加载。

Custom Grid Adapter

<强> Lazy load of images in ListView