5

まず第一に、グリッドビューで画像を表示してスクロール時にスムーズにするために、すでにいくつかのことを行っています

1. バックグラウンド スレッドでインターネットから画像を読み込む

AsyncTask acyncTask ;
HandlerThread handlerThread ;

 URL imageUrl = new URL(link);<br>
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is=conn.getInputStream();
            final Bitmap bitmap = BitmapFactory.decodeStream(is);

2.ビットマップをサンプルサイズにしてメモリを節約する

final BitmapFactory.Options option = new BitmapFactory.Options();
    option.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mFile.getPath(),
            option);
    option.inSampleSize = calculateInSampleSize(option , mSize , mSize);
    option.inJustDecodeBounds = false;
    option.inPurgeable = true ;
    option.inDither = false ;
    option.inScaled = false ;
    option.inPreferredConfig = Bitmap.Config.ARGB_8888;

3. デコードされたビットマップを保存するキャッシュを作成する

LruCache lruCache = new LruCache<String , Bitmap>();

デコードされたビットマップを取得しbaseadapter getView(); ますlruCache.get(key)

4.ビットマップがハンドラーを介してデコードされたときの遅延ロード

 Handler handler = new Handler();
        handler.post(new Runnable(){
           public void run(){
              imageView.setimageBitmap(bitmap);
          }
      });

今、私は大きな問題に直面しています。スクロールしているときにまだ少し遅れますgetView () は約2 ~ 6 ミリ秒しか費やさず、コードを呼び出してイメージ フォーム ワーカー スレッドを非同期ロードするため、一部のアプリが非常にスムーズにロードできる理由が本当にわかりません。私の場合、画面のスクロールが非常にスムーズに見えない場合、いくつかの提案が適用できますか?

編集: スクロールしているときに、キャッシュにあるビットマップが画面に表示されます。高速スクロールすると、画像を表示するのに十分なスクロールがないように見えます。スクロールがスムーズではなくなります。キャッシュ内のビットマップ

アダプターコードは次のとおりです。

if (convertView == null) {
        convertView = layoutInflater.inflate(
                R.layout.row_display_image_grid, null);
        viewHolder = new DisplayImageGridViewHolder();
        viewHolder.background = (RelativeLayout) convertView
                .findViewById(R.id.background);
        viewHolder.image = (ImageView) convertView.findViewById(R.id.image);
        viewHolder.text = (TextView) convertView.findViewById(R.id.text);
        viewHolder.position = position;
        viewHolder.text.setEllipsize(TruncateAt.END);
        viewHolder.text.setTypeface(typeFace);
        viewHolder.image.setOnClickListener(this);
        viewHolder.image.setOnLongClickListener(this);
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (DisplayImageGridViewHolder) convertView.getTag();
    }

viewHolder.position = position;
imageLoader.loadImage(imageLinkList.get(position), viewHolder.image);
return convertView;
4

2 に答える 2

4

以下は、私が使用する LazyLoader の例です。ビットマップに SoftReferences を使用していることに注意してくださいLruCache

これにより、Web / SD カード / メモリから非同期的に画像が読み込まれ、プレースホルダー画像からフェードイン効果が作成されます。

public class ImageLoader {

private static MemoryCacheNew memoryCache=new MemoryCacheNew();
private static FileCache fileCache;

private static BitmapFactory.Options bitmapOptions;

private static int mInSampleSize;



public ImageLoader(Context context, int inSampleSize){


    fileCache=new FileCache(context);        

    context = null;

    bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inSampleSize = mInSampleSize = inSampleSize;
    bitmapOptions.inPreferredConfig = Config.RGB_565;
    bitmapOptions.inInputShareable = true;
    bitmapOptions.inDither = false;

}

final static int PLACEHOLDER_IMAGE = R.drawable.store_placeholder;

public void DisplayImage(String url, ImageView imageView,  boolean checkTags){

    try{

    new AsyncPhotoTask(imageView, url, checkTags).execute();

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

}

public void DisplayImage(String url, ImageView imageView)
{
      DisplayImage(url, imageView, true); 

}


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


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

    //from web
    try {
        Bitmap bitmap=null;

        URL imageUrl;

            imageUrl = new URL(url);


        HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
        conn.setConnectTimeout(30000);
        conn.setReadTimeout(30000);
        InputStream is=conn.getInputStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        is.close();
        os.close();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Exception ex){
       ex.printStackTrace();
       return null;
    }
}

//decodes image and scales it to reduce memory consumption
private static Bitmap decodeFile(File f){
    try {
        return BitmapFactory.decodeStream(new FileInputStream(f), null, bitmapOptions);

    } catch (FileNotFoundException e) {

    } catch (OutOfMemoryError err){
        System.gc();
    } 

    return null;
}


private static class AsyncPhotoLoad extends AsyncTask<Void, Void, TransitionDrawable>{

    private Bitmap bmp;
    private ImageView imageView;
    private String url;
    private boolean checkTags;

    public AsyncPhotoLoad(ImageView imageView, String url, boolean checkTags
            ){
        this.imageView = imageView;
        this.url = url;
        this.checkTags = checkTags;
    }

    @Override
    protected TransitionDrawable doInBackground(Void... arg0) {

        //check that this is the correct imageview



        TransitionDrawable transition = null;

        try{
            if(checkTags){
            String tag = (String)imageView.getTag();    
            if(!tag.equals(url))
                return null;
            }

        bmp = getBitmap(url);

        if(bmp != null){
            memoryCache.put(url, bmp, mInSampleSize);    

            Drawable oldDrawable = imageView.getDrawable();

            if(!(oldDrawable instanceof TransitionDrawable)){

                Drawable layers[] = new Drawable[2];                    
                layers[0] = imageView.getDrawable();
                layers[1] = new BitmapDrawable(bmp);

               transition = new TransitionDrawable(layers);

            }



        }

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

        return transition;
    }

    @Override
    protected void onPostExecute(TransitionDrawable result) {
        if(result != null){
            try{            
                if(checkTags){                      
                        String tag = (String)imageView.getTag();    
                        if(!tag.equals(url)){
                            return;
                        }
                }

                   imageView.setImageDrawable(result);
                   result.startTransition(300);



            } catch(Exception e){
                e.printStackTrace();
            }
        } else {
            if(checkTags){
            try{
                String tag = (String)imageView.getTag();    
                if(!tag.equals(url))
                    return;

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


        }
    }

}



private static class AsyncPhotoTask extends AsyncTask<Void, Void, Bitmap>{

    private ImageView imageView;
    private String url;
    private boolean checkTags;


    public AsyncPhotoTask(ImageView imageView, String url, boolean checkTags){

        this.imageView = imageView;
        this.url = url;
        this.checkTags = checkTags;
    } 


    @Override
    protected Bitmap doInBackground(Void... params) {
        try{
        if(checkTags)
            imageView.setTag(url);  

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

        return memoryCache.get(url, mInSampleSize);
    }


    @Override
    protected void onPostExecute(Bitmap result) {
        try{
        if(result!=null && !result.isRecycled()){


            imageView.setImageBitmap(result);   
        }
        else
        {   

            imageView.setImageResource(PLACEHOLDER_IMAGE);            
            new AsyncPhotoLoad(imageView, url, checkTags).execute();      

        }    

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



}





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

public static void clearMemory(){
    memoryCache.clear();
}

public static class MemoryCacheNew {
    private HashMap<String, CachedBitmap> cache=new HashMap<String, CachedBitmap>();

    public Bitmap get(String id, int sampleSize){
        if(!cache.containsKey(id))
            return null;

        if(cache.get(id) == null)
            return null;

        if(cache.get(id).sampleSize != sampleSize)
            return null;

        SoftReference<Bitmap> ref = cache.get(id).softBitmap;
        return ref.get();
    }

    public void put(String id, Bitmap bitmap, int sampleSize){
        cache.put(id, new CachedBitmap(bitmap, sampleSize));
    }

    public void clear() {
        cache.clear();
    }



    private static class CachedBitmap {
        public SoftReference<Bitmap> softBitmap;
        public int sampleSize;

        public CachedBitmap(Bitmap bitmap, int sampleSize){
            this.softBitmap = new SoftReference<Bitmap>(bitmap);
            this.sampleSize = sampleSize;
        }
    }
}


}


public class FileCache {

private File cacheDir;

public FileCache(Context context){
    //Find the dir to save cached images
    if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
        cacheDir=new File(context.getExternalCacheDir(),Consts.STORE_CACHE);
    else
        cacheDir=context.getCacheDir();
    if(!cacheDir.exists())
        cacheDir.mkdirs();
}

public File getFile(String url){
    //I identify images by hashcode. Not a perfect solution, good for the demo.
    String filename=String.valueOf(url.hashCode());
    File f = new File(cacheDir, filename);
    return f;

}

public void clear(){
    File[] files=cacheDir.listFiles();
    for(File f:files)
        f.delete();
}

}

次のように呼び出します。

imageLoader.DisplayImage(url, holder.image);
于 2012-04-25T10:23:15.570 に答える
0

各ビットマップのサイズが最適であることを確認してください...それらはコンテナのサイズとほぼ同じである必要があります。RemoteView 経由で送信する前に、できる限り縮小してください。onAppWidgetOptionsChanged を使用して、ウィジェットのサイズを計算できます。

また、最適なパフォーマンスを得るには、setImageViewBitmap の代わりに setImageViewUri (コンテンツ プロバイダを使用) を使用してみてください。

于 2013-09-10T14:21:55.403 に答える