is it possible to load the Thumbnails of a GridView in an Asynctask, to prevent lags on scrolling the GridView?
That's the code of my Asynctask:
#SuppressLint("StaticFieldLeak")
public class AsyncTaskLoadFiles2 extends AsyncTask<Void, String, Void> {
File targetDirector;
public AsyncTaskLoadFiles2(ImageAdapter2 adapter) {
myTaskAdapter2 = adapter;
}
#Override
protected void onPreExecute() {
String targetPath = "/sdcard/Android/data/de.myapps.gridtest/files/Download/.Videos";
targetDirector = new File(targetPath);
myTaskAdapter2.clear2();
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage("Loading Videos, please wait...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(false);
progressDialog.show();
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
File[] files = targetDirector.listFiles();
for (File file : files) {
publishProgress(file.getAbsolutePath());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (isCancelled()) break;
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
myTaskAdapter2.add2(values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result) {
myTaskAdapter2.notifyDataSetChanged();
progressDialog.dismiss();
super.onPostExecute(result);
}
}
And here's the code of my ImageAdapter:
public class ImageAdapter2 extends BaseAdapter {
private Context mContext;
ArrayList<String> itemList = new ArrayList<String>();
public ImageAdapter2(Context c) {
mContext = c;
}
void add2(String path) {
itemList.add(path);
}
void clear2() {
itemList.clear();
}
void remove2(int index) {
itemList.remove(index);
}
public String getPath(int position) {
return itemList.get(position);
}
#Override
public int getCount() {
return itemList.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return itemList.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#SuppressLint("ResourceType")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 420));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
thumbnail = ThumbnailUtils.createVideoThumbnail(getPath(position),
MediaStore.Images.Thumbnails.MICRO_KIND);
// Set the decoded bitmap into ImageView
imageView.setImageBitmap(thumbnail);
return imageView;
}
}
So what I would like to know is if it is possible to load the thumbnail Bitmap in the Asynctask, because with this code the app lags. (I'm using a TabbedActivity so all this code is part of a Fragment)
Have a look at
https://developer.android.com/topic/performance/graphics/cache-bitmap
BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
task.execute(resId);
You can create an AsyncTask that loads the image into the ImageView
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
...
// Decode image in background.
#Override
protected Bitmap doInBackground(Integer... params) {
final Bitmap bitmap = decodeSampledBitmapFromResource(getResources(), params[0], 100, 100));
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if(result != null) {
myImgView.setImageBitmap(result);
}
}
}
You just call BitmapWorkerTask.Execute with parameters in the constructor from the getView() method in your adapter.
BitmapWorkerTask task = new BitmapWorkerTask(imageView, filePath);
Make the constructor
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private ImageView imageView;
private String filePath;
public BitmapWorkerTask(ImageView imageView, String filePath) {
this.imageView = imageView;
this.filePath = filePath;
}
....
//Get your bitmap
//Set Bitmap onPostExecute
Related
I use a customize listview control to display image and other informations. The listview control is little slow when I scroll it to display more content.
After I test the control, I find the function SetControlsValue to do many works. I must to do some work to improve it.
The Method 1 is my way, is it correct? is there other the better way?
Method 1
private void SetControlsValue(ViewHolder holder,int position){
holder.mCheckBox.setChecked(mListCheckedStatus.get(position));
new BMPOperation().execute(position,holder);
new LongOperation().execute(position,holder);
}
private class BMPOperation extends AsyncTask<Object, Void, Bitmap> {
private ViewHolder myHolder;
#Override
protected Bitmap doInBackground(Object... params) {
int position=(Integer)params[0];
myHolder=(ViewHolder)params[1];
Bitmap mBitmap=mListVideo.get(position).GetBitmapOfVideo();
return mBitmap;
}
#Override
protected void onPostExecute(Bitmap mBitmap) {
try {
if (mBitmap != null) {
myHolder.imageViewthumb.setImageBitmap(mBitmap);
}
}catch (Exception e){
Utility.LogError(e.getMessage());
}
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
private class LongOperation extends AsyncTask<Object, Void, String> {
private ViewHolder myHolder;
#Override
protected String doInBackground(Object... params) {
int position=(Integer)params[0];
myHolder=(ViewHolder)params[1];
String s=mListVideo.get(position).fileName
+"\n"+mContext.getResources().getString(R.string.TitleResolution)+ mListVideo.get(position).GetResolution()
+"\n"+mContext.getResources().getString(R.string.TitleSize)+mListVideo.get(position).GetSize()
+"\n"+mContext.getResources().getString(R.string.TitleDuration)+mListVideo.get(position).GetDuration();
return s;
}
#Override
protected void onPostExecute(String result) {
myHolder.tvInfo.setText(result);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
The Function SetControlsValue
private void SetControlsValue(ViewHolder holder,int position){
holder.mCheckBox.setChecked(mListCheckedStatus.get(position));
Bitmap mBitmap=mListVideo.get(position).GetBitmapOfVideo();
try {
if (mBitmap != null) {
holder.imageViewthumb.setImageBitmap(mBitmap);
}
}catch (Exception e){
Utility.LogError(e.getMessage());
}
String s=mListVideo.get(position).fileName
+"\n"+mContext.getResources().getString(R.string.TitleResolution)+ mListVideo.get(position).GetResolution()
+"\n"+mContext.getResources().getString(R.string.TitleSize)+mListVideo.get(position).GetSize()
+"\n"+mContext.getResources().getString(R.string.TitleDuration)+mListVideo.get(position).GetDuration();
holder.tvInfo.setText(s);
}
ListVideoAdapter.java
public class ListVideoAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private List<Video> mListVideo;
private List<Boolean> mListCheckedStatus;
public ListVideoAdapter (Context context){
mContext=context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mListVideo= VideoHelper.ListVideo(mContext);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return mListVideo.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.layout_adapter_video, null);
IniControls(holder,convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
SetControlsPosition(holder,position);
SetControlsValue(holder,position);
SetControlsEvent(holder);
return convertView;
}
private void IniControls(ViewHolder holder,View convertView){
holder.mCheckBox=(CheckBox) convertView.findViewById(R.id.chSelect);
holder.imageViewthumb=(ImageView)convertView.findViewById(R.id.imageViewVideo);
holder.tvInfo = (TextView) convertView.findViewById(R.id.tvInfo);
holder.imageViewTrim=(ImageView)convertView.findViewById(R.id.imageViewTrim);
holder.imageViewShare=(ImageView)convertView.findViewById(R.id.imageViewShare);
holder.imageViewInfo=(ImageView)convertView.findViewById(R.id.imageViewInfo);
holder.imageViewDelete=(ImageView)convertView.findViewById(R.id.imageViewDelete);
}
private void SetControlsPosition(ViewHolder holder,int position){
holder.id=position;
holder.mCheckBox.setId(position);
holder.imageViewthumb.setId(position);
holder.tvInfo.setId(position);
holder.imageViewTrim.setId(position);
holder.imageViewShare.setId(position);
holder.imageViewInfo.setId(position);
holder.imageViewDelete.setId(position);
}
private void SetControlsValue(ViewHolder holder,int position){
holder.mCheckBox.setChecked(mListCheckedStatus.get(position));
Bitmap mBitmap=mListVideo.get(position).GetBitmapOfVideo();
try {
if (mBitmap != null) {
holder.imageViewthumb.setImageBitmap(mBitmap);
}
}catch (Exception e){
Utility.LogError(e.getMessage());
}
String s=mListVideo.get(position).fileName
+"\n"+mContext.getResources().getString(R.string.TitleResolution)+ mListVideo.get(position).GetResolution()
+"\n"+mContext.getResources().getString(R.string.TitleSize)+mListVideo.get(position).GetSize()
+"\n"+mContext.getResources().getString(R.string.TitleDuration)+mListVideo.get(position).GetDuration();
holder.tvInfo.setText(s);
}
private void SetControlsEvent(final ViewHolder holder) {
}
}
class ViewHolder {
int id;
CheckBox mCheckBox;
ImageView imageViewthumb;
TextView tvInfo;
ImageView imageViewTrim;
ImageView imageViewShare;
ImageView imageViewInfo;
ImageView imageViewDelete;
}
Added
I have read the sample code of UniversalImageLoader.
I don't think UniversalImageLoader control fit my requirement.
ImageLoader need to pass URL par
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], imageView, options);
but in my app, there are other two codes which spend much time.
Bitmap mBitmap=mListVideo.get(position).GetBitmapOfVideo();
String s=mListVideo.get(position).fileName +"\n"+mContext.getResources().getString(R.string.TitleResolution)+ mListVideo.get(position).GetResolution() +"\n"+mContext.getResources().getString(R.string.TitleSize)+mListVideo.get(position).GetSize() +"\n"+mContext.getResources().getString(R.string.TitleDuration)+mListVideo.get(position).GetDuration();
so I think I need the other better way to improve code.
BTW, in my function Bitmap mBitmap=mListVideo.get(position).GetBitmapOfVideo() not only get the thumbnail of a video, but also I need merger a Play icon to the thumbnail, so I don't think I can use ImageLoader.getInstance().displayImage("file:///mnt/sdcard/myvideo.mp4", imageView).
Here are suggestion to improve the performance:
Use recyclerview instead of Listview - Recycler view recycles the child items which is out of the screen and thus freeing up the memory
Use picasso image loader - It loads images on other thread and thus doesn't block your UI thread. Also it caches the image in file/memory (you can configure it) so when user tries to play with scroll your UI doesn't get stuck. This means images which has been already downloaded from network will be reloaded from cache automatically. ( http://square.github.io/picasso/)
Showing Bitmaps on UiThread is a lazy operation. So you should you UniversalImageLoader to display your bitmaps/thumbnails of videos in SetControlsValue function.
Hope this helps.
I have a ListView of elements composed with ImageView. I get a new image using an AsyncTask and in the onPostExecute(Object result) method I set the image using setImageUri(Uri uri) but it doesn't gets updated.
If I change of activity or between apps, image is shown perfectly, but I want to show the image immediately.
I tried calling invalidate() with all the combinations of the ImageView, the extended BaseAdapter, the parent ListView, but nothing worked. I tried many other techniques like calling setImageResource(0), setImageUri(null), but no results...
EDITED:
Here, part of the code:
public class ThingItemAdapter extends BaseAdapter {
protected List<Thing> things;
LayoutInflater inflater;
public ThingItemAdapter(Context context, List<Thing> things) {
this.things = things;
this.inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return things.size();
}
#Override
public Thing getItem(int position) {
return things.get(position);
}
#Override
public long getItemId(int position) {
return things.get(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = this.inflater.inflate(R.layout.thing_list_item, parent, false);
holder.thingImageView = (ImageView) convertView.findViewById(R.id.thing_preview);
holder.button = (ImageButton) convertView.findViewById(R.id.apply_button);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Thing thing = things.get(position);
final long thingId = thing.getId();
final Uri thingUri = thing.getPicture();
holder.thingImageView.setImageURI(thingUri);
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// generate new file
final TypedFile typedFile = new TypedFile("multipart/form-data", new File(thingUri.getPath()));
new ReadAndStorePictureTask()
.execute(new Object[] { typedFile, holder.thingImageView, thing });
}
});
// item detailed view listener
holder.thingImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent((ThingApplication) ThingApplication.getContext(), ThingActivity.class);
intent.putExtra(ThingActivity.EXTRA_THING_ID, thingId);
context.startActivity(intent);
}
});
return convertView;
}
private class ViewHolder {
ImageView thingImageView;
ImageButton button;
}
private class ReadAndStorePictureTask extends AsyncTask<Object, Void, Void> {
ImageView imageView;
Thing thing;
ViewGroup parent;
protected Void doInBackground(Object... params) {
final TypedFile typedFile = (TypedFile) params[0];
imageView = (ImageView) params[1];
thing = (Thing) params[2];
((ThingApplication) ThingApplication.getContext()).getClient().apply(typedFile,
new Callback<Response>() {
#Override
public void failure(RetrofitError error) {
...
}
#Override
public void success(Response nothing, Response response) {
try {
byte[] bytes = ThingApplication.getBytesFromStream(response.getBody().in());
Uri newImageURI = Uri.parse("uri://valid_uri"); // whatever, it exists in real code
thing.setPicture(newImageURI);
File file = ((ThingApplication) ThingApplication.getContext())
.getFileFromURI(newImageURI); // this method works
ThingApplication.saveBytesToFile(bytes, file.getAbsolutePath());
thingService.storeThing(thing);
} catch (Exception e) {
...
}
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
imageView.setImageURI(thing.getPicture());
// force redraw. FIXME not working
/*
* ANSWER HERE, PLEASE
*/
}
}
}
How can I show the updated URI immediately inside onPostExecute(Object result) method?
onPostExecute you update the list of images that it's linked to the ListView adapter and after that you notify the adapter that you changed the items in the list by calling:
adapter.notifyDataSetChanged();
You can do something like this:
-Change third parameter in asynctask call.
new ReadAndStorePictureTask().execute(
new Object[] { typedFile, holder.thingImageView, pos });
-Then, modify the list items inside asynctask and refresh.
private class ReadAndStorePictureTask extends AsyncTask<Object, Void, Void> {
ImageView imageView;
int position;
ViewGroup parent;
protected Void doInBackground(Object... params) {
final TypedFile typedFile = (TypedFile) params[0];
imageView = (ImageView) params[1];
position = (Integer) params[2];
((ThingApplication) ThingApplication.getContext()).getClient().apply(typedFile,
new Callback<Response>() {
#Override
public void failure(RetrofitError error) {
...
}
#Override
public void success(Response nothing, Response response) {
try {
byte[] bytes = ThingApplication.getBytesFromStream(response.getBody().in());
Uri newImageURI = Uri.parse("uri://valid_uri"); // whatever, it exists in real code
things.get(position).setPicture(newImageURI);
File file = ((ThingApplication) ThingApplication.getContext())
.getFileFromURI(newImageURI); // this method works
ThingApplication.saveBytesToFile(bytes, file.getAbsolutePath());
thingService.storeThing(things.get(position));
} catch (Exception e) {
...
}
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
notifyDataSetChanged();
}
}
Good luck!
Hi please forgive me if I am mistaking when explaining the problem . I have a Custom Base adapter in which there is two imageView and two TextView and I am usning an Async task to set the image from the URL. it sets the image but changes the image again automatically.
below is the code for the adapter .
public class SharedPhotosAdapter extends BaseAdapter{
Context context;
LayoutInflater inflater;
public static ArrayList<HashMap<String, String>> data;
ImageLoader imageLoader;
private static final String BRANCH="Branch";
private static final String DATE="DateTime";
private static final String STARS="Stars";
private static final String IMAGE_URL="URL";
private static final String USER_NAME="UserName";
TextView name,date,comment;
ImageView pro_image,shared_image;
public SharedPhotosAdapter(Context con,ArrayList<HashMap<String, String>> result) {
// TODO Auto-generated constructor stub
context=con;
data=result;
inflater = (LayoutInflater)context.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(context);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View rowView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
Bitmap bitmap=null;
ImageView image = null;
HashMap<String, String> result=data.get(position);
if(rowView==null)
{
rowView=inflater.inflate(R.layout.shared_photos_item, null);
holder=new ViewHolder();
holder.name=(TextView)rowView.findViewById(R.id.textView1);
holder.date=(TextView)rowView.findViewById(R.id.textView4);
holder.comment=(TextView)rowView.findViewById(R.id.textView3);
holder.pro_image=(ImageView)rowView.findViewById(R.id.imageView1);
holder.shared_image=(ImageView)rowView.findViewById(R.id.imageView2);
rowView.setTag(holder);
}
else
{
holder = (ViewHolder)rowView.getTag();
}
new DownloadImageTask(holder.shared_image).execute(result.get(IMAGE_URL));
holder.name.setText(result.get(USER_NAME));
holder.date.setText(result.get(DATE));
holder.comment.setText(result.get(BRANCH));
return rowView;
}
public class ViewHolder
{
TextView name,date,comment;
ImageView pro_image,shared_image;
}
}
Here is the Async task that i am using for setting the image from the url
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
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) {
}
return mIcon11;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
bmImage.setImageBitmap(result);
}
}
it setting randomly any image to the image view just cant figure out where i am going wrong.
A little help will be appreciable.
thanks
I would suggest you to try Picasso to remove the hassle of downloading images/caching etc.
Once you have the jar in your workspace, all you need to do in the getView() method of the adapter class is this.
Picasso.with(context).load(result.get(IMAGE_URL)).into(holder.shared_image);
No need of the DownloadAsyncTask.
As #zapl also suggested in the comment, there are other libraries like Volley and UniversalImageLoader, but I liked Picasso. You can also easily apply transformations like rounded-image using the Transformation interface provided by Picasso.
I am trying to add Loading dialog in following code to fetch image from server and display it in Gallery view. it shows blank screen untill image comes. please help me how do i show Loading dialog while getting image from server.
Here is the code, pls help.
public class ImagedisplaytestActivity extends Activity {
private ImageView leftArrowImageView;
private ImageView rightArrowImageView;
private Gallery gallery;
public int selectedImagePosition;
private GalleryImageAdapter galImageAdapter;
private String bitmapImg = "";
Bitmap bitmap = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupUI();
}
private void setupUI() {
Intent i = getIntent();
Bundle extras=i.getExtras();
bitmapImg = extras.getString("BitmapImage");
selectedImagePosition = extras.getInt("Pos");
leftArrowImageView = (ImageView) findViewById(R.id.left_arrow_imageview);
rightArrowImageView = (ImageView) findViewById(R.id.right_arrow_imageview);
gallery = (Gallery) findViewById(R.id.gallery);
leftArrowImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (selectedImagePosition > 0) {
--selectedImagePosition;
}
gallery.setSelection(selectedImagePosition, false);
}
});
rightArrowImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (selectedImagePosition < DetailView.bitmapURL.size() - 1) {
++selectedImagePosition;
}
gallery.setSelection(selectedImagePosition, false);
}
});
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
selectedImagePosition = pos;
if (selectedImagePosition > 0 && selectedImagePosition < DetailView.bitmapURL.size() - 1) {
leftArrowImageView.setImageDrawable(getResources().getDrawable(R.drawable.arrow_left_disabled));
rightArrowImageView.setImageDrawable(getResources().getDrawable(R.drawable.arrow_right_disabled));
} else if (selectedImagePosition == 0) {
leftArrowImageView.setImageDrawable(getResources().getDrawable(R.drawable.arrow_left_enabled));
} else if (selectedImagePosition == DetailView.bitmapURL.size() - 1) {
rightArrowImageView.setImageDrawable(getResources().getDrawable(R.drawable.arrow_right_enabled));
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
galImageAdapter = new GalleryImageAdapter(this, DetailView.bitmapURL);
gallery.setAdapter(galImageAdapter);
if (DetailView.bitmapURL.size() > 0) {
gallery.setSelection(selectedImagePosition, false);
}
if (DetailView.bitmapURL.size() == 1) {
rightArrowImageView.setImageDrawable(getResources().getDrawable(R.drawable.arrow_right_disabled));
}
}
public class GalleryImageAdapter extends BaseAdapter {
private Activity context;
private ImageView imageView;
private List<String> plotsImages;
private ViewHolder holder;
public GalleryImageAdapter(Activity context, List<String> plotsImages) {
this.context = context;
this.plotsImages = plotsImages;
}
#Override
public int getCount() {
return plotsImages.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
holder = new ViewHolder();
imageView = new ImageView(this.context);
imageView.setPadding(3, 3, 3, 3);
convertView = imageView;
holder.imageView = imageView;
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.imageView.setLayoutParams(new Gallery.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY);
try {
bitmap = DownloadImage(plotsImages.get(position));
holder.imageView.setImageBitmap(bitmap);
bitmap = null;
} catch (Exception e) {
e.printStackTrace();
}
return imageView;
}
private class ViewHolder {
ImageView imageView;
}
private Bitmap DownloadImage(String URL){
Bitmap bitmap = null;
try {
InputStream in = OpenHttpConnection(URL);
bitmap = BitmapFactory.decodeStream(in);
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return bitmap;
}
private InputStream OpenHttpConnection(String urlString) throws IOException{
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection)) {
throw new IOException("Not an HTTP connection");
}
try{
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
}
catch (Exception ex){
throw new IOException("Error connecting");
}
return in;
}
}
#Override
public void onBackPressed() {
DetailView.bundleID = DetailView.idList.get(selectedImagePosition);
super.onBackPressed();
}
}
You should use AsyncTask!
See this also!
& in Vogella Example will clear your doubt .
see this for the lazy image Loading DEMO! on github.
use assynctask,
in that assynctask method you can write your getting images from server in doinbackground(),
in that time you can display alert dialogue using preexectue(), after loading from server just dismiss the alert dialogue in postexectue().
This code work for me
private class LoadGlobalDataSearch extends AsyncTask<String, Void, Void>
{
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
progressdialog.dismiss();
}
#Override
protected Void doInBackground(String... params)
{
//Load your images this task
setupUI();
return null;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
progressdialog = ProgressDialog.show(MainActivity.this, "",getString(R.string.inprogress));
}
}
call this class in your oncreate method
new loadImages().execute(0);
You can use a progress dialoge until the image is downloaded then remove the dialog.
In OpenHttpConnection add this --
dialog = ProgressDialog.show(DutyRotaActivity.this, "",
"Please wait for few seconds...", true);
in DownloadImage dissmiss the dialog.
dialog.dismiss();
Or you can use asynchronous task too. cause network operation should always do on other thread
not in the main thread. In that case in preExecute add the dialog and in postExecute dissmiss the dialog. And in doinbackground call your downloadimage function that will also do the tricks.
Edit
Here is a complete source code and a library to load image lazily in the listView. I think its also can help you to solve your issue.Thanks
https://github.com/nostra13/Android-Universal-Image-Loader
My code as follows:
public class wall extends Activity {
GridView webgridview;
Button web;
ProgressDialog pd;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wall);
pd = ProgressDialog.show(wall.this,"Loading", "Please Wait...",true);
new Thread() {
public void run() {
try {
webgridview.setAdapter(new WebImageAdapter(wall.this));
}catch(Exception e)
{
}
handler.sendEmptyMessage(0);
pd.dismiss();
}
}.start();
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
Toast.makeText(wall.this, "finished", 1).show();
}
};
And my adapter class as follows. I code progress dialog in above class only.
public class WebImageAdapter extends BaseAdapter {
private Context mContext;
public static String[] myRemoteImages = {
"http://www.evergreenhits.com/ad/wallpapers/3d_1.jpg",
"http://www.evergreenhits.com/ad/wallpapers/3d_2.jpg",
"http://www.evergreenhits.com/ad/wallpapers/3d_3.jpg",
"http://www.evergreenhits.com/ad/wallpapers/3d_4.jpg",
"http://www.evergreenhits.com/ad/wallpapers/3d_5.jpg"
};
public WebImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
//return animals.length;
return this.myRemoteImages.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
// create a new ImageView for each item referenced by the Adapter
public ImageView getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
imageView = new ImageView(mContext);
if (convertView == null) {
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
try {
URL aURL = new URL(myRemoteImages[position]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Drawable d=Drawable.createFromStream(bis, "src Name");
bis.close();
is.close();
imageView.setImageDrawable(d);
} catch (IOException e) {
Log.e("DEBUGTAG", "Remote Image Exception", e);
}
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
return imageView;
}
The progress Dialog doesnt work properly. It shows and suddenly gone before the images loaded in gridview. Please help me asap.
Use AsyncTask:
calling:
dialog=ProgressDialog.show(wall.this,"Loading", "Please Wait...",true);
doback dob=new doback();
dob.execute();
Class
class doback extends AsyncTask<URL, Integer, Long>
{
#Override
protected Long doInBackground(URL... arg0)
{
try
{
//getImagepaths from Server
}
catch(Exception e)
{
}
return null;
}
protected void onProgressUpdate(Integer... progress)
{
}
protected void onPostExecute(Long result)
{
try
{
webgridview.setAdapter(new WebImageAdapter(wall.this));
dialog.dismiss();
}
catch(Exception e)
{
e.printStackTrace();
dialog.dismiss();
}
}
}
Adapter Code is some like this:
class WebImageAdapter extends BaseAdapter{
// #Override
public int getCount() {
return names.length;
}
// #Override
public Object getItem(int position) {
return null;
}
// #Override
public long getItemId(int position) {
return 0;
}
// #Override
public View getView(int pos, View convertView, ViewGroup parent) {
View row=getLayoutInflater().inflate(R.layout.nameitem,null);
ImageView image=(ImageView)row.findViewById(R.id.image);
image.setImageBitmap(convertImage(myRemoteImages[position]))// convertImage is to convert url to bitmap
return row;
}
}
Edit - From the Android Developer Documentation:ProgressDialog
This class was deprecated in API level 26.
ProgressDialog is a modal
dialog, which prevents the user from interacting with the app. Instead
of using this class, you should use a progress indicator like
ProgressBar, which can be embedded in your app's UI. Alternatively,
you can use a notification to inform the user of the task's progress.
setAdapter(), do not take more time, its getView() of Adapter class on each time hit web and taking time. So using of progressDialog on setAdapter is not appropriate. On scroll of your grids it took lot of time by using your code, as getView() call automatically on scrolling view.
you should have a reference from LazyList for loading image from web and placing them in ImageView.