Reputation: 2070
Hello stackoverflow
I'm trying to develop an application like Gallery
for a particular directory of SD Card
. For example I have took WhatsApp Images
directory, here is my code
public class WhatsAppInboxImagesActivity extends Activity {
private ImageAdapter imageAdapter;
private ProgressDialog pd;
ArrayList<String> f = null;
File[] listFile;
Button btnDelete;
HashSet<String> selectedFile = null;
GridView imagegrid;
AlertDialog alertDialog = null;
static
{
File noFile = new File(Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images/Sent/.nomedia");
if(noFile.exists())
{
noFile.delete();
}
}//End of static block
private void initialize()
{
imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
btnDelete = (Button) findViewById(R.id.btnDeleteImg);
selectedFile = new HashSet<String>();// list of file paths boolean checked
f = new ArrayList<String>();// list of file paths
}//End of initialize method
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_whats_app_images_inbox);
this.initialize();
getFromSdcard();
imageAdapter = new ImageAdapter();
/*
* Performing time consuming actions
*/
new AsyncTask<Void, Void, Void>()
{
@Override
protected void onPreExecute()
{
pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
"Loading..", "Please Wait", true, false);
}// End of onPreExecute method
@Override
protected Void doInBackground(Void... params)
{
return null;
}// End of doInBackground method
@Override
protected void onPostExecute(Void result)
{
imagegrid.setAdapter(imageAdapter);
imageAdapter.notifyDataSetChanged();
pd.dismiss();
}
}.execute((Void[]) null);
btnDelete.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
new AsyncTask<Void, Void, Void>()
{
@Override
protected void onPreExecute()
{
pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
"Loading..", "Please Wait", true, false);
}// End of onPreExecute method
@Override
protected Void doInBackground(Void... params)
{
@SuppressWarnings("rawtypes")
Iterator iterator = selectedFile.iterator();
while (iterator.hasNext())
{
new File(iterator.next().toString()).delete();
}//End of while loop
return null;
}// End of doInBackground method
@Override
protected void onPostExecute(Void result)
{
pd.dismiss();
}//End of onPostExecute method
}.execute((Void[]) null);
finish();
startActivity(getIntent());
}//End of onClick method
});//End of btnDelete anonymous class
}//End of onCreate method
public void getFromSdcard()
{
File file = new File( Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images");
if (file.isDirectory())
{
listFile = file.listFiles();
for (int i = 0; i < listFile.length; i++)
{
if(listFile[i].isDirectory())
{
continue;
}
f.add(listFile[i].getAbsolutePath());
}//End of for loop
}//End of if condition
}//End of getFromSdcard method
public class ImageAdapter extends BaseAdapter
{
private LayoutInflater mInflater;
public ImageAdapter()
{
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}//End of ImageAdapter constructor
public int getCount()
{
return f.size();
}//End of getCount method
public Object getItem(int position)
{
return position;
}//End of getItem method
public long getItemId(int position)
{
return position;
}//End of getItemId method
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.galleryitem, null);
holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);
convertView.setTag(holder);
}//End of if condition
else
{
holder = (ViewHolder) convertView.getTag();
}//End of else
BitmapFactory.Options options = new BitmapFactory.Options();
// will results in a much smaller image than the original
options.inSampleSize = 4;
// don't ever use a path to /sdcard like this, but I'm sure you have a sane way to do that
// in this case nebulae.jpg is a 19MB 8000x3874px image
final Bitmap b = BitmapFactory.decodeFile(f.get(position), options);
holder.imageview.setImageBitmap(b);
return convertView;
}//End of getView method
}//End of ImageAdapter instance inner class
class ViewHolder
{
ImageView imageview;
CheckBox checkbox;
int id;
}//End of ViewHolder instance inner class
}//End of WhatsAppImagesActivity
So far every thing is good, but the problem is images gets loaded all at one shot
, so scrolling is very slow and some times OutOfMemoryException
occurs though decoded
file with BitMapFactory
, can any one help me to solve this puzzle please.
Edit:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.list_layout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.text.setTextColor(Color.BLACK);
viewHolder.image = (ImageView) view.findViewById(R.id.image);
viewHolder.image.setVisibility(View.GONE);
viewHolder.cb = (CheckBox) view.findViewById(R.id.item_check_box);
viewHolder.pb = (ProgressBar) view.findViewById(R.id.progressBar);
view.setTag(viewHolder);
} else {
view = convertView;
}
final int pos = position;
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.image.setTag(list.get(position).getURL());
holder.image.setId(position);
PbAndImage pb_and_image = new PbAndImage();
pb_and_image.setImg(holder.image);
pb_and_image.setPb(holder.pb);
new DownloadImageTask().execute(pb_and_image);
return view;
}
Thanks.
Upvotes: 0
Views: 4120
Reputation: 3190
This could help: UniversalImageLoader
And that's what I did:
/**
* UniversalImageLoader載入遠端圖片,僅使用RAM做圖片快取 (Load pic & use RAM as cache)
* @param android.content.Context
* @author https://github.com/nostra13/Android-Universal-Image-Loader
* @param android.widget.ImageView - 顯示圖片的元件 (your image container)
* @param int - 載入失敗的預設圖片Resource ID (default pic if load fail, I put default pic in resources folder)
* @param java.lang.String - 檔案URL (pic URL or path)
*/
public static void imageLoaderMemoryCache(Context context, final ImageView img, final int failImgID, String url)
{
ImageLoader imageLoader=ImageLoader.getInstance();
ImageLoaderConfiguration config=new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(100, 100) // max width, max height
.threadPoolSize(5)
.threadPriority(Thread.NORM_PRIORITY+1)
.denyCacheImageMultipleSizesInMemory()
.tasksProcessingOrder(QueueProcessingType.FIFO)
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.enableLogging()
.build();
imageLoader.init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.cover_sample)
.cacheInMemory(true)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.bitmapConfig(Bitmap.Config.RGB_565)
.delayBeforeLoading(1)
.displayer(new FadeInBitmapDisplayer(500))
.build();
imageLoader.displayImage(url, img, options, new ImageLoadingListener()
{
@Override
public void onLoadingStarted(String url, View view)
{img.setImageResource(failImgID);} //一開始先顯示預設圖 (display default pic at first)
@Override
public void onLoadingFailed(String url, View view, FailReason failReason)
{img.setImageResource(failImgID);}
@Override
public void onLoadingComplete(String url, View view, Bitmap loadedImage)
{}
@Override
public void onLoadingCancelled(String url, View view)
{}
});
}
Usage (ListView)
public View getView(...)
{
vh.imgCover=(ImageView)convertView.findViewById(R.id.imgCover);
//...
// some stuff
//...
Util.imageLoaderDiskCache(getActivity(), vh.imgCover, R.drawable.cover_sample, "(pic file path)");
}
Hope it helps~
Upvotes: 0
Reputation: 4348
You should use Lazy loading
visit this tutorial for lazy loading here Its very easy. Let me know if you have any issue on it.
Edit
public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String path = Environment.getExternalStorageDirectory()+"/WhatsApp/Media/WhatsApp Images";
final List<Model> list = new ArrayList<Model>();
final File file = new File(path);
final ProgressDialog dialog = ProgressDialog.show(MainActivity.this, "",
"Please Wait...", true);
new Thread(new Runnable() {
public void run() {
dismissDialog(dialog);
for(File fileChild : file.listFiles()){
list.add(get(fileChild.getName(), fileChild.getAbsolutePath()));
}
}
}).start();
ArrayAdapter<Model> adapter = new MyCustomArrayAdapter(this, list);
setListAdapter(adapter);
}
public void dismissDialog(final ProgressDialog dialog) {
runOnUiThread(new Runnable() {
public void run() {
dialog.dismiss();
}
});
}
private Model get(String s, String url) {
return new Model(s, url);
}
}
Upvotes: 3