laggy Listview with ImageView and Executor Framework - android

I have a ListView with custom items, like this one:
The grey square is an ImageView. The data to fill the ListView comes from a database in the form of a Cursor. But the images are not directly stored in the database, but in the SDCard, the database only holds a String reference to them.
In the beginning I was decoding the Image into a Bitmap from the overriden CursorAdapter's bindView() callback method:
Bitmap bmp = BitmapFactory.decodeFile(imageLocation);
holder.imageHolder.setImageBitmap(bmp);
But the ListView Scrolling was very laggy. So i read about Executor framework and implemented it, replacing the previous code with the following:
ImageView imageView = holder.imageHolder;
asyncImageLoader.DisplayImage(imageLocation, imageView);
And creating the AsyncImageLoader class. Which creates, in its constructor, a thread pool with maximum of 5 worker threads to take care of the Runnables sent to the work queue. Then, when I call the DisplayImage() method from my custom CursorAdapter, it checks if the location String contains a url. If it does, an ImageLoader Runnable is sent to the thread pool's work queue. If the location contains "N/A", a default image is set to the ImageView.
When an available worker thread takes care of the ImageLoader Runnable, the image in the SDCard is decoded into a Bitmap, and a ImageDisplayer Runnable is sent to the Main Thread's message queue, to show the image in the UI:
public class AsyncImageLoader {
ExecutorService executorService;
Handler handler = new Handler();
public AsyncImageLoader() {
this.executorService = Executors.newFixedThreadPool(5);
}
public void DisplayImage(String location, ImageView imageView) {
if(!location.matches("N/A")) {
queueImageDecoding(location, imageView);
} else {
imageView.setImageDrawable(imageView.getContext().getResources().getDrawable(R.drawable.not_available));
}
}
private void queueImageDecoding(String location, ImageView imageView) {
executorService.execute(new ImageLoader(location, imageView));
}
class ImageLoader implements Runnable {
private String location;
private ImageView imageView;
public ImageLoader(String location, ImageView imageView) {
this.location = location;
this.imageView = imageView;
}
#Override
public void run() {
Bitmap bmp = BitmapFactory.decodeFile(location);
handler.post(new ImageDisplayer(bmp, imageView));
}
}
class ImageDisplayer implements Runnable {
private Bitmap bitmap;
private ImageView imageView;
public ImageDisplayer(Bitmap bitmap, ImageView imageView) {
this.bitmap = bitmap;
this.imageView = imageView;
}
#Override
public void run() {
if(bitmap != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
The problem is that I am still getting the Laggy scrolling. If I get rid of the code inside ImageLoader.run() method, the scrolling is perfect. Isn't that code supposed to be processed in a worker thread? What am i missing here?
UPDATE
Since the Views in the ListView are reused when the scrolling happens, the Bitmaps returned from the worker thread, are set several times in a single ImageView.
So the possible solutions are:
To avoid setting the old Bitmap when the ListView item has already been reused.
Or even better, cancel the task.
I am cancelling the tasks using a Future object. Which is stored in the holder tagged to the item View inside the custom CursorAdapter:
public class MyCustomAdapter extends CursorAdapter {
...
public AsyncImageLoader asyncImageLoader;
private static class ViewHolder {
ImageView imageHolder;
TextView text1Holder;
TextView text2Holder;
TextView text3Holder;
Button buttonHolder;
Future<?> futureHolder;
}
public MyCustomAdapter(Context context, Cursor c, int flags) {
...
this.asyncImageLoader = new AsyncImageLoader();
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
...
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder)view.getTag();
String location = ...;
ImageView imageView = holder.imageHolder;
if(holder.futureHolder == null) {
holder.futureHolder = asyncImageLoader.DisplayImage(location, imageView);
} else {
if(!holder.futureHolder.isDone())
holder.futureHolder.cancel(true);
holder.futureHolder = asyncImageLoader.DisplayImage(location, imageView);
}
...
}
}
Each time an item view is reused, I check if the holder's future object isDone(). If it is not, I cancel the task with Future.cancel(true). But now, the problem is that the tasks complete too fast to be cancelled. if I put the worker thread to sleep, for let's say 1 second, then the task lasts long enough to be cancelled and the ListView scrolling works better. But i have to wait 1 second for the images to appear and I don't want that.
public class AsyncImageLoader {
....
public Future<?> DisplayImage(String location, ImageView imageView) {
if(!location.matches("N/A")) {
return executorService.submit(new ImageLoader(location, imageView));
} else {
imageView.setImageDrawable(imageView.getContext().getResources().getDrawable(R.drawable.not_available));
return null;
}
}
class ImageLoader implements Runnable {
private String location;
private ImageView imageView;
public ImageLoader(String location, ImageView imageView) {
this.location = location;
this.imageView = imageView;
}
#Override
public void run() {
boolean interrupted = false;
try {
if(!Thread.currentThread().isInterrupted()) {
Thread.sleep(1000);
Bitmap bmp = BitmapFactory.decodeFile(location);
handler.post(new ImageDisplayer(bmp, imageView));
}
} catch (InterruptedException consumed) {
interrupted = true;
} finally {
if(interrupted)
Thread.currentThread().interrupt();
}
}
}
...
}
The second solution would be to let the tasks complete, but prevent setting the old Bitmap when the ListView item has already been reused. But i can't figure out how to do it. Any suggestions?

Ok, originally I get the images from a Web Service, and store them in the SDCard. From the samples I downloaded, I trusted the service was returning all the images with the same dimensions. WRONG! some of them are bigger than expected and were causing the lag when were set in the ImageView. I just had to scale them down. Load a Scaled Bitmap Version into Memory

Related

Android: How to show progressbar on each imageview in griidview while sending multipal images to server

Hi I got frustrated while searching solution for my problem.My problem is that i have a gridview to show all images which i selected from gallery.I want to display progressbar on each images in gridview.and while uploading images to server using multipart i want too update progressbar..
I displayed progressbar on each imageview but i am unable to show progress on each progressbar.
SO please help me to show how to show progress bar and their respective process on each imageview.
thanks in advance
Create a interface for an observer:
interface ProgressListener {
void onProgressUpdate(String imagePath, int progress);
}
Let the view holder implement that observer and know the image path:
public class ViewHolder implements ProgressListener {
ImageView imgQueue;
ProgressBar pb;
TextView tv;
String imagePath; //set this in getView!
void onProgressUpdate(String imagePath, int progress) {
if (!this.imagePath.equals(imagePath)) {
//was not for this view
return;
}
pb.post(new Runnable() {
pb.setProgress(progress);
});
}
//your other code
}
The adapter shall hold an map of observers for a particular image path/uri whatever and have an method that is called by the upload/download task. Also add methods to add and remove observer:
public class SelectedAdapter_Test extends BaseAdapter {
private Map<String, ProgressListener> mProgressListener = new HashMap<>();
//your other code
synchronized void addProgressObserver(String imagePath, ProgressListener listener) {
this.mListener.put(imagePath, listener);
}
synchronized void removeProgressObserver(String imagePath) {
this.mListener.remove(imagePath);
}
synchronized void updateProgress(String imagePath, int progress) {
ProgressListener l = this.mListener.get(imagePath);
if (l != null) {
l.onProgressUpdate(imagePath, progress);
}
}
//other code
}
In getView of the adapter register the view holder as an observer:
public View getView(final int i, View convertView, ViewGroup viewGroup) {
//other code
holder.imagePath = data.get(i).getSdcardPath();
this.addProgressObserver(holder.imagePath, holder);
return convertView;
}
The problem right now is, that we register the observer but don't unregister. So let the adapter implement the View.addOnAttachStateChangeListener:
public class SelectedAdapter_Test extends BaseAdapter implements View.addOnAttachStateChangeListener {
//other code
void onViewAttachedToWindow(View v) {
//We ignore this
}
void onViewDetachedFromWindow(View v) {
//View is not visible anymore unregister observer
ViewHolder holder = (ViewHolder) v.getTag();
this.removeProgressObserver(holder.imagePath);
}
//other code
}
Register that observer when you return the view.
public View getView(final int i, View convertView, ViewGroup viewGroup) {
//other code
convertView.addOnAttachStateChangeListener(this);
return convertView;
}
Finally you are able to tell the views what the progress is:
#Override
public void transferred(long num) {
int progress = (int) ((num / (float) totalSize) * 100);
selectedAdapter.onProgressUpdate(listOfPhotos.get(i).getSdcardPath(), progress);
}
One final problem remains, what if the activity is gone while the upload is in progress? You need to check if the activity is still alive. Maybe setting a flag in the adapter to true in onCreate and to false in onDestroy would do the trick. Then the last code fragment could check that flag and not notify the adapter on changes anymore.
So thats basically the idea of how to solve this. Does it work? I don't know I wrote it from scratch without any testing. And even if it does, you still have to manage the states when the progress is 0 or 100. But I leave that to you. Also you might want to change the BaseAdapter for an recyclerView so that we can get rid of the View.addOnAttachStateChangeListener.
add boolean in adapter class
public SelectedAdapter_Test(Context c, ArrayList<CustomGallery> data, boolean showProgress) {
mContext = c;
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.data = data;
this.showProgress = showProgress;
}
changes in Adapter class getView
holder.pb = (ProgressBar) convertView.findViewById(R.id.progressbar);
if (showProgress)
holder.pb.setVisibility(View.VISIBLE);
else
holder.pb.setVisibility(View.GONE);
make changes in doFileUpload
private void doFileUpload(View v) {
View vi = v;
for (i = 0; i < listOfPhotos.size(); i++) {
<--your task-->
}
//**important**
SelectedAdapter_Test mTest = new SelectedAdapter_Test(context,data,false);
// set above adapter object respectively;
mList.setadapter(mTest);
}
FYI. pass showProgress value as true for the first time when you set adapter.

Laggy Recycler View without even any code?

I was using recycler view to List Images but it was getting laggy after even caching and all. So I Decided to use Glide library but still laggy as hell. I finally thought to check with just a single drawable and still it's laggy. I don't get why. Please help. Here is the code. There is not much code still. You can see the code I was using for my Image Viewing commented out.
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageHolder>
{
private File file;
private String logging=getClass().getSimpleName();
private int size;
private MemCache memCache;
private Context context;
private Bitmap bitmap;
public ImageAdapter(File file,int Size,MemCache memCache,Context context)
{
this.file = file;
size=Size;
this.memCache=memCache;
this.context=context;
bitmap=BitmapFactory.decodeResource(context.getResources(),R.drawable.empty_photo);
}
#Override
public ImageHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new ImageHolder(new ImageView(context),size);
}
#Override
public void onBindViewHolder(ImageHolder holder, int position)
{
Glide.with(context).load(R.drawable.empty_photo).into(holder.getImageView());
// if (memCache.get(file.listFiles()[position].toString())!=null)
// {
// holder.getImageView().setImageBitmap(memCache.get(file.listFiles()[position].toString()));
// }
// else
// {
// ImageSyncTask imageSyncTask = new ImageSyncTask(size, holder.getImageView(),memCache);
// imageSyncTask.executeOnExecutor(imageSyncTask.THREAD_POOL_EXECUTOR, file.listFiles()[position]);
// }
// Glide.with(context).load(file.listFiles()[position]).crossFade().into(holder.getImageView());
}
#Override
public int getItemCount()
{
if (file!=null&&file.listFiles()!=null) return file.listFiles().length;
else return 0;
}
public static class ImageHolder extends RecyclerView.ViewHolder
{
private ImageView imageView;
public ImageHolder(View itemView,int size)
{
super(itemView);
imageView=(ImageView)itemView;
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setMinimumWidth(size);
imageView.setMinimumHeight(size);
}
public ImageView getImageView()
{
return imageView;
}
public void clearImage()
{
imageView.setImageResource(android.R.color.transparent);
}
}
}
I know there is one loading Bitmap but still its just one. That shouldn't make that much lag. And yes I have used the typical setImageBitmap instead of Glide but still laggy.
There is the view holder. Just Simple function. And I was previously using a proper layout for it but it was not working as well. In this I have just used New ImageView() and setParamaters just to make sure if there was a problem in Layout.
Please Help. I don't get why the typical Adapter is creating Lag.
Original MainActivity
public class MainActivity extends AppCompatActivity
{
RecyclerView recyclerView;
int cnum;
private MemCache memCache;
private String logging=getClass().getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DisplayMetrics displayMetrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int maxmem=(int)Runtime.getRuntime().maxMemory()/1024;
int cache_mem=maxmem/10;
memCache=new MemCache(cache_mem);
int orientation=getResources().getConfiguration().orientation;
if (orientation== Configuration.ORIENTATION_PORTRAIT)
cnum=3;
else cnum=5;
recyclerView=(RecyclerView)findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new GridLayoutManager(getApplicationContext(),cnum));
recyclerView.setAdapter(new ImageAdapter(getGallery(),displayMetrics.widthPixels/cnum,memCache,getApplicationContext()));
}
private File getGallery()
{
return new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(),"Trial");
}
}
I have also tried and removed maximum of calls which can be removed to make sure there is not much task on UI thread.
Doing disk I/O on the main application thread is a common source of "jank", as that I/O may take a bit of time. StrictMode can help you determine where you are doing disk I/O on the main application thread.
In general, you want to load your model data (e.g., a list of files) on a background thread, then work off of the in-memory representation of that model data on the main application thread.

Images from URL appear and disappear on ListView Scroll

Hello I fill my ListView with a BaseAdapter, here a Download an Image from url, then I set the BitMap result in ImageView inside the xml row.
It works fine, but when I scroll the images appear and disapear in diferent places.
This my Code:
Activity:
public class MyActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
lvData = (ListView) findViewById(R.id.listview1);
AdapterClass adapter = new AdapterClass(this, String[] urls);
lvData.setAdapter(adapter);
}
}
Adapter:
public class PopularAdapter extends BaseAdapter {
private String[] mList;
private LayoutInflater mLayotInflalter;
public PopularAdapter(Context context, String[] list) {
mList = list;
mLayotInflalter = ((Activity) context).getLayoutInflater();
}
#Override
public int getCount() {
return mList.size();
}
#Override
public Object getItem(int position) {
return mList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
WrapperRow wrapper;
if (convertView == null) {
convertView = mLayotInflalter.inflate(R.layout.row, null);
wrapper = new WrapperRow (convertView);
convertView.setTag(wrapper);
} else
wrapper = (WrapperRow ) convertView.getTag();
// //
new DownloadImage(wrapper.getImageView()).execute(mList.[position]);
return convertView;
}
}
Image Downloader Class:
public class DownloadImage extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImage(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
Can you help me please? :D
This happens because the views get recycled in a ListView. This answer does a good job of explaining how the recycling mechanism works. Now coming on to your case, whenever getView gets called in your adapter, you are kick starting a new AsyncTask that downloads the image at the given url and sets it in the imageView inside WrapperRow.
Let's see why exactly the views flicker. Consider that you have a wrapper rows - wr1, wr2, wr3 .... wr8 and they get recycled by the listView (i arbitrarily chose to explain with 8 rows. the listView could use less or more). As soon as getView gets called the first time, you inflate a wrapper row (wr1) and then pass it to the AsyncTask which downloads the image & then sets it. Now you scroll through the list and the same process takes place for views wr2 to wr8 and on further scrolling it is time to recycle the views and wr1 comes into play again. You kick start another asyncTask to download the image but you never cleared the imageView (it already holds the first image now) and when the task is done downloading it sets the new image in imageview and this is when you an image disappearing and a new image showing up. When you scroll through the list, you see this happening repeatedly for all the rows!!
You could use any of the libraries like Picasso or UIL, but if you wanna spin up your own implementation remember these things
Don't hold on to strong references of views in asyncTasks (this would prevent the activity instance from GC even if it gets destroyed leading to memory leaks)
Whenever you start a new asyncTask make sure to cancel the previous asyncTask (if any) that still works with this view
And it always better to use caches (memory & disk)

Unable to load thumbnails into ListView

I am currently attempting to make a simple image gallery like the now deprecated Android Gallery. From this gallery the user can also navigate to a simple image editor by selecting an image form the gallery. After a lot of Googling I managed to find a HorizontalListView here which is exactly what I need. Initially I had a lot of success with this by just inserting the images in my folder as compressed bitmaps. Since then however I have found this video from Google I/O in which they create an image gallery and an image editor; similar to what I am attempting to create. There are however two main differences between my app and theirs:
they use a GridView for their gallery and I use the aforementioned HorizontalListView
I am attempting to only load images from a specified target path rather than just all images on the SD card.
So far I am unable to adapt their code to mine as none of the images are loading into my gallery. As with the video I use an AsyncTask to load my thumbnails:
private class ThumbnailAsyncTask extends AsyncTask<Long, Void, Bitmap>
{
//The ImageView we will be adding the thumbnail to
private final ImageView mTarget;
public ThumbnailAsyncTask(ImageView target)
{
mTarget = target;
}
#Override
protected Bitmap doInBackground(Long... params)
{
final long photoID = params[0];
final Bitmap result = MediaStore.Images.Thumbnails.getThumbnail(
getContentResolver(), photoID, MediaStore.Images.Thumbnails.MINI_KIND, null);
return result;
}
#Override
protected void onPreExecute()
{
mTarget.setTag(this);
}
#Override
protected void onPostExecute(Bitmap result)
{
if (mTarget.getTag() == this)
{
mTarget.setImageBitmap(result);
mTarget.setTag(null);
}
}
}
and I am using a CursorAdapter for the images in the gallery:
private class PhotoAdapter extends CursorAdapter
{
public PhotoAdapter(Context context)
{
super(context, null, false);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor)
{
final long photoId = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
final ImageView imageView = (ImageView) view.findViewById(android.R.id.icon);
/*
* Cancel any pending thumbnail task, since this view is now bound
* to new thumbnail
*/
final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) imageView.getTag();
if (oldTask != null)
oldTask.cancel(false);
/*
* If we arrived here, either cache is disabled or cache miss, so we
* need to kick task to load manually
*/
final ThumbnailAsyncTask task = new ThumbnailAsyncTask(imageView);
imageView.setImageBitmap(null);
imageView.setTag(task);
task.execute(photoId);
}
}
With the following CursorLoader
final LoaderCallbacks<Cursor> mCursorCallbacks = new LoaderCallbacks<Cursor>()
{
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
final String[] columns = {BaseColumns._ID};
return new CursorLoader(NewProjectActivity.this,
Uri.fromFile(new File(mTargetPath)), columns, null, null,
MediaStore.Images.Media.DATE_ADDED + " DESC");
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
mAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
mAdapter.swapCursor(null);
}
};
getLoaderManager().initLoader(LOADER_CURSOR, null, mCursorCallbacks);
Any ideas on why none of my images are loading?
The basic problem here is, bindView() method is not waiting for asynctask's result. You need to notify your list view when some of its content get changed.
You can do the following changes.
1) Change task.execute(photoId); to task.execute(photoId).get(); this will force your bindView() method to wait till you get your image. This approach is not advisable but it will help you to understand the exact problem.
OR
2) In onPost() of asynctask, invalidate your list view's old content and try to reload it with new content.
mAdapter.notifyDataSetChanged();
mAdapter.notifyDataSetInvalidated();
OR
3) Personally i will suggest you to finish all network operation first (i.e. fetching images ) by changing your code structure and then after try to set your adapter with the prefetched data. This is not a perfect solution but it worked in my case.

Android How can i download images with AsyncTask to sdcard and on completion show on listview on the right item?

I want to download some images through AsyncTask to SDcard and on completion to show them on an listview. When the download starts an progress bar is shown, when it stops will show the image downloaded on sdcard.
I saw that are a lot of posts with lazy-load, but what i want is to show a progress bar before showing the image, and i want to be stored on sdcard.
The bellow code works almost ok, but the problem is that it doesnt show the right picture on the right item all the time when it is downloading the image. I am using the bellow in the adapter:
public View getView(final int position, View convertView, ViewGroup parent) {
final PooHolder holder;
if(convertView == null){
convertView = inflater.inflate(R.layout.item_poo, null);
holder = new PooHolder();
holder.tvTime = (TextView)convertView.findViewById(R.id.tvTime);
holder.tvMessage = (TextView)convertView.findViewById(R.id.tvMessage);
holder.btnDislike = (ImageButton)convertView.findViewById(R.id.btnDislike);
holder.btnLike = (ImageButton)convertView.findViewById(R.id.btnLike);
holder.btnReport = (ImageButton)convertView.findViewById(R.id.btnReport);
holder.bar = (ProgressBar)convertView.findViewById(R.id.progressBar1);
holder.bar1 = (ProgressBar)convertView.findViewById(R.id.progressBar2);
holder.bar2 = (ProgressBar)convertView.findViewById(R.id.progressBar3);
holder.tvLikes = (TextView)convertView.findViewById(R.id.tvLikes);
holder.tvComments = (TextView)convertView.findViewById(R.id.tvComments);
holder.tvDislikes = (TextView)convertView.findViewById(R.id.tvDislike);
holder.imgPoo = (ImageView)convertView.findViewById(R.id.imgPoo);
convertView.setTag(holder);
}else{
holder = (PooHolder)convertView.getTag();
}
final Poo poo = list.get(position);
String vote = poo.getVote();
if(poo.getDrawablePath()!=null){
if(!poos.get(position).isDownloadComplete()){
Log.i(DEBUG, poo.getMessage());
holder.bar2.setVisibility(View.VISIBLE);
holder.imgPoo.setImageBitmap(BitmapFactory.decodeFile(poo.getDrawablePath()));
holder.imgPoo.setVisibility(View.INVISIBLE);
if(!poos.get(position).getDownloadState(Poo.DOWNLOAD_START)){
DownloadImageTask task = new DownloadImageTask(poo, holder.bar2, holder.imgPoo);
task.setOnDownloadListener(new OnDownloadListener(){
public void onDownloadStarted() {
poos.get(position).startDownload();
}
public void onDownloadFinished(final Bitmap bmp) {
poos.get(position).stopDownload();
}
});
task.execute(poo.getImagePath());
}
}else{
holder.bar2.setVisibility(View.INVISIBLE);
holder.imgPoo.setVisibility(View.VISIBLE);
holder.imgPoo.setImageBitmap(BitmapFactory.decodeFile(poo.getDrawablePath()));
}
}else{
holder.bar2.setVisibility(View.INVISIBLE);
holder.imgPoo.setVisibility(View.VISIBLE);
holder.imgPoo.setImageResource(R.drawable.icon);
}
....
The DownloadImageTask.java:
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private final String DEBUG = "DownloadImageTask";
private String url;
private String imagePath;
private OnDownloadListener listener;
private Bitmap bmp;
private ProgressBar bar;
private ImageView img;
private Poo poo;
public DownloadImageTask(Poo poo, ProgressBar bar, ImageView img) {
this.img = img;
this.bar = bar;
this.poo = poo;
}
public void onPreExecute(){
super.onPreExecute();
listener.onDownloadStarted();
bar.setVisibility(View.VISIBLE);
img.setImageBitmap(BitmapFactory.decodeFile(poo.getDrawablePath()));
img.setVisibility(View.INVISIBLE);
}
public void setOnDownloadListener(OnDownloadListener listener){
this.listener = listener;
}
#Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
this.imagePath = poo.getImagePath();
// params comes from the execute() call: params[0] is the url.
if(imagePath != null && !imagePath.isEmpty()){
String file = imagePath.substring(imagePath.lastIndexOf("/") + 1, imagePath.length());
return BoopoohooUtils.downloadImage(params[0], file);
}else{
return null;
}
}
#Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
Log.i(DEBUG, "bitmap " + bitmap);
bar.setVisibility(View.INVISIBLE);
img.startAnimation(BoopoohooUtils.fadeIn());
img.setVisibility(View.VISIBLE);
img.setImageBitmap(bitmap);
listener.onDownloadFinished(bitmap);
}
}
So to start you will need to use the progress method on the async task class. Link . Then for your method on the top create a variable for passing through different sequence let's say 5,4,3,2,1. When it starts it goes by 5 and decrements to 1 then application will go to post and do whatever gui interactions you are doing.

Categories

Resources