I'm using this code to show Images, as I run it without thread It works correctly but with using thread I just get Image views without any picture inside them. its important for me to use thread for this part of my program because its very slow :(
here is my code :
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Log.e("sara" , "this part takes time");
LayoutInflater inflater = getLayoutInflater();
convertView = getLayoutInflater().inflate(R.layout.gallery_gridsq, parent, false);
iv = (ImageView) convertView.findViewById(R.id.icon);
final File file = new File(Uri.parse(getItem(position).toString()).getPath());
//File file = new File("/text.jpg");
Runnable runnable = new Runnable() {
#Override
public void run() {
Bitmap bmp = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
try {
bmp = BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
iv.setImageBitmap(bmp);
}
};
new Thread(runnable).start();
return convertView;
}
}
Use AsyncTask.
Doc: https://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask enables proper and easy use of the UI thread. This class
allows you to perform background operations and publish results on the
UI thread without having to manipulate threads and/or handlers.
Do your heavy operation in doInBackground() and set the image to imageView in onPostExecute().
Related
Here in my code I'm setting a picture into an ImageView in my MyTask class which is using AsyncTask, but as I run my code just one or two ImageViews has pictures and the others are empty showing the default picture.
Is there any problems with the thread?
Here is my code:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Log.e("sara" , "this part takes time");
LayoutInflater inflater = getLayoutInflater();
convertView = getLayoutInflater().inflate(R.layout.gallery_gridsq, parent, false);
iv = (ImageView) convertView.findViewById(R.id.icon);
file = new File(Uri.parse(getItem(position).toString()).getPath());
new myTask().execute();
return convertView;
}
private class myTask extends AsyncTask <Void , Void ,Bitmap> {
#Override
protected Bitmap doInBackground(Void... params) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
try {
bmp = BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return bmp;
}
#Override
protected void onPostExecute(Bitmap aVoid) {
iv.setImageBitmap(aVoid);
}
}
This is because you are overriding the iv(imageview) object every time when getView() method is called and because MyTask is an asynch task in which doInBackground() is called asynchronously on background thread and onPostExecute() called on main thread after that. So the onPostExecute will only update the current imageview. You have to set the bitmap on every image view of grid. This solution should work for you:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Log.e("sara" , "this part takes time");
LayoutInflater inflater = getLayoutInflater();
convertView = getLayoutInflater().inflate(R.layout.gallery_gridsq, parent, false);
ImageView iv = (ImageView) convertView.findViewById(R.id.icon);
File file = new File(Uri.parse(getItem(position).toString()).getPath());
new myTask(iv, file).execute();
return convertView;
}
private class MyTask extends AsyncTask <Void , Void ,Bitmap> {
Imageview iv;
File file;
public void MyTask(Imageview iv, File file)
{
this.iv=iv;
this.file= file;
}
#Override
protected Bitmap doInBackground(Void... params) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
try {
bmp = BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return bmp;
}
#Override
protected void onPostExecute(Bitmap aVoid) {
iv.setImageBitmap(aVoid);
}
}
i consider that you are try to load an image using a url
you can user image loader reference (such as universal image loader) which is best for loading images
here is the code you can have
first of download the universal image loader library from the below
https://github.com/nostra13/Android-Universal-Image-Loader
You have to add this method your application level class so you don't need to write multiple times
public static void initImageLoader(Context context) {
// This configuration tuning is custom. You can tune every option, you
// may tune some of them,
// or you can create default configuration by
// ImageLoaderConfiguration.createDefault(this);
// method.
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(
context);
config.threadPriority(Thread.NORM_PRIORITY - 2);
config.denyCacheImageMultipleSizesInMemory();
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
config.tasksProcessingOrder(QueueProcessingType.LIFO);
config.writeDebugLogs(); // Remove for release app
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config.build());
}
Then in Adapter class you have to just add the below code to load image
// For Image Display options - Failed , Success and Error
// Add this is in your adapter constructor
DisplayImageOptions userimgoptions = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.profile_pic_no_border)
.showImageForEmptyUri(R.drawable.profile_pic_no_border)
.showImageOnFail(R.drawable.profile_pic_no_border).cacheInMemory(true)
.cacheOnDisk(true).bitmapConfig(Bitmap.Config.RGB_565).build();
// in you getview method just use this signle line code to load image
ImageLoader.getInstance().displayImage(modelFeeds.getUserAvatarOriginal(), myHolder.img_profilepicture, userimgoptions);
i hope this will help you
Set the Imageview using Glide Library
Step1: Include the Dependencies in your build.gradle file
compile 'com.github.bumptech.glide:glide:3.7.0'
Step2: Include the Glide in Java file
String fileName = "1.jpg";
String completePath = Environment.getExternalStorageDirectory() + "/" +
fileName;
File file = new File(completePath);
Uri imageUri = Uri.fromFile(file);
Glide.with(this)
.load(imageUri)
.placeholder(R.drawable.no_media)
.into(imgView);
I need to run some parts of my code with thread. But I got problem with accessing the variables from run() function. The variables (also the function arguments) needs to be defined as final, but as I do this I cannot change their value inside run() function. For example now variable iv is not accessible in run() method.
Is there any way I could handle this problem?
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
convertView = getLayoutInflater().inflate(R.layout.gallery_gridsq, parent, false);
ImageView iv = (ImageView) convertView.findViewById(R.id.icon);
final File file = new File(Uri.parse(getItem(position).toString()).getPath());
Runnable runnable = new Runnable() {
#Override
public void run() {
Bitmap bmp = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
try {
bmp = BitmapFactory.decodeStream(new FileInputStream(file), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
iv.setImageBitmap(bmp);
}
};
new Thread(runnable).start();
return convertView;
}
What you need to do here is to make iv final:
final ImageView iv = (ImageView) convertView.findViewById(R.id.icon);
In this context final means that you cannot change reference to the object iv points to, but you still can call any methods of it. Also beware of creating new Thread for each view, I would suggest using thread pool represented by ExecutorService instead.
I need to parse the json output in my xml. Parsing is done but the image is not seen in the xml. Android log says this -
12-22 14:26:34.472: I/System.out(6037): resolveUri failed on bad bitmap uri: "base_url"/sites/default/files/pictures/picture-6175010166.jpg
Is there anything wrong in my below code can any body suggest me ?
HashMap<String, String> listview = new HashMap<String, String>();
String title = "";
String teaser="";
String createdon = "";
String profile_image = "";
try {
title = jListview.getString("title");
teaser = jListview.getString("teaser");
createdon = jListview.getString("created");
profile_image = jListview.getString("profile_image");
listview.put("title", title);
listview.put("teaser", teaser);
listview.put("created", createdon);
listview.put("profile_image", profile_image);
//listview.put("profile_image", picture);
} catch (JSONException e) {
System.out.println( "Bad Error" + e.toString());
e.printStackTrace();
}
return listview;
This is my main activity code where iam showing the result
try{
/** Getting the parsed data as a List construct */
lists = listJsonParser.parse(obj);
int imageCount = lists.size();
}
}catch(Exception e){
Log.d("Exception Main",e.toString());
}
/** Keys used in Hashmap */
String[] from = { "title","teaser","created","profile_image"};
/** Ids of views in listview_layout */
int[] to = { R.id.title,R.id.teaser,R.id.createdon,R.id.list_image};
/** Instantiating an adapter to store each items
* R.layout.listview_layout defines the layout of each item
*/
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), countries, R.layout.home_layout, from, to);
return adapter;
LoGcat:12-22 14:26:34.382: I/System.out(6037): resolveUri failed on bad bitmap uri:
your Error says Below:
12-22 14:26:34.472: I/System.out(6037): resolveUri failed on bad bitmap uri: "base_url"/sites/default/files/pictures/picture-6175010166.jpg
you need to download the image and then set it as bitmap. HERE is one of the many examples.
you can not set Direct web url to ImageView for setting ImageView src. you first create an custom Adapter by extending BaseAdapter for ListView and in getView you will need to first download image from Url as Bitmap and then set it to ImageView as:
public class CustomAdapter extends BaseAdapter{
#Override
public View getView(int position, View convertView,
ViewGroup parent) {
if(convertView == null){
LayoutInflater layoutInflater = (LayoutInflater)
getSystemService(LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.
inflate(R.layout.layout_row, null);
}
Bitmap test = getbitpam(maptemp.get("profile_image"));
imgview=(ImageView) convertView.findViewById(R.id.img_list);
imgview.setImageBitmap(test);
return convertView;
}
}
//get image from server
public Bitmap getbitpam(String url) {
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(url).openStream(), IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 1;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);
} catch (IOException e) {
Log.e(TAG, "Could not load Bitmap from: " + url);
} finally {
closeStream(in);
closeStream(out);
}
return bitmap;
}
}
I want to read images from URL and show it in android gallery widget.
so I wrote below code in onCreate() method .
list = GuideDAO.getAllImages(businessId);
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setSpacing(2);
// Set the adapter to our custom adapter (below)
if(list.size() > 0)
{
g.setAdapter(new ImageAdapter(this,list));
}
This is my ImageAdapter
public class ImageAdapter extends BaseAdapter {
List<Images> glist = null;
private String url;
public ImageAdapter(Context c,List<Images> lst) {
mContext = c;
glist = lst;
int i=0;
for (Images id : glist) {
url = id.getImageURL(); // Getting URL
InputStream inStream = null;
if (url.startsWith("http")) {
url = url.replace(" ", "%20");
HttpURLConnection conn;
try {
conn = (HttpURLConnection)new URL(url).openConnection();
conn.setDoInput(true);
conn.connect();
inStream = conn.getInputStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
inStream = new FileInputStream(url);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inPurgeable = true;
Bitmap b = BitmapFactory.decodeStream(inStream, null, options);
mImageCollection[i]=b;
i++;
}
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageBitmap(mImageCollection[position]);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(136, 88));
return i;
}
private Context mContext;
private String[] mImageURLs = {};
private Bitmap[] mImageCollection = {};
}
This throw error because it not in Thread. How can I change this code so that URL reading and image loads in background?
So I have changed my ImageAdapter by using SmartImageView , which handles background thread and caching.
public class ImageAdapter extends BaseAdapter {
List<ImageGallery> glist = null;
private String url;
public ImageAdapter(Context c,List<ImageGallery> lst) {
mContext = c;
glist = lst;
int i=0;
al = new ArrayList<String>();
for (ImageGallery id : glist) {
al.add(id.getImageURL());
}
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("deepak", "getview gallery");
SmartImageView i = new SmartImageView(mContext);
i.setImageUrl(al.get(position));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(136, 88));
return i;
}
private Context mContext;
private String[] mImageURLs = {};
private ArrayList<String> al;
private Bitmap[] mImageCollection = {};
private Integer[] mImageIds = {};
}
But my getView() is not getting called now.
you can make use of Smart Image view. SmartImageView is a drop-in replacement for Android’s standard ImageView which additionally allows images to be loaded from URLs or the user’s contact address book. Images are cached to memory and to disk for super fast loading.
Please refer the following link for more info https://github.com/loopj/android-smart-image-view .hope this may help u to accomplish ur task
I'd suggest writing an AsyncImageLoader class and having it handle image downloads from http. This way you can cache and manage everything on separate threads and have it set the image to the view once the loading is complete. Also you could use this class throughout the application if you want to download images elsewhere.
you could call something like mImageLoader.loadImage(myImageView, Url) in your adapter and it would drop it in once it was finished loading.
if you want more details let me know :)
I have a listview in which I'm loading all the images (as previews) from the user's SD card. I have a custom SimpleCursorAdapter and when I override the getView() method, I try to start background threads for the image loading.
What I'm trying to do is basically "lazy loading" the image previews into the listview using background threads or something. I'm open for new solutions. The main problem is that scrolling is ungodly slow since loading images is so expensive an operation.
Here's the relevant code I'm trying:
public class listOfImages extends SimpleCursorAdapter {
private Cursor c;
private Context context;
public listOfImages(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
}
public View getView(int pos, View inView, ViewGroup parent) {
View v = inView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.image_item, null);
}
this.c.moveToPosition(pos);
int columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
String name = this.c.getString(columnIndex);
columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
String size = this.c.getString(columnIndex);
columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String data = this.c.getString(columnIndex); //gives the filename
TextView sTitle = (TextView) v.findViewById(R.id.image_title);
sTitle.setText(name);
imagePreviewLoader ipl = new imagePreviewLoader(v, data);
ipl.mainProcessing();
v.setTag(data);
v.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Image: " + v.getTag(), Toast.LENGTH_SHORT).show();
String filename = (String) v.getTag();
Intent intent = new Intent(context, ViewImage.class);
intent.putExtra("filename", filename);
context.startActivity(intent);
}
});
return v;
}
}
And now the background threading that I'm trying:
public class imagePreviewLoader {
private Handler handler = new Handler();
private View v;
private String data;
public imagePreviewLoader(View v, String data) {
this.v = v;
this.data = data;
}
protected void mainProcessing() {
Thread thread = new Thread(null, doBackground, "Background");
thread.start();
}
private Runnable doBackground = new Runnable() {
public void run() {
backgroundThreadProcessing();
}
};
private void backgroundThreadProcessing() {
handler.post(doUpdateGUI);
}
private Runnable doUpdateGUI = new Runnable() {
public void run() {
updateGUI();
}
};
private void updateGUI() {
ImageView img = (ImageView) v.findViewById(R.id.image_view);
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 30;
bfo.inTargetDensity = 50;
Bitmap bm = BitmapFactory.decodeFile(data, bfo);
img.setImageBitmap(bm);
}
}
The issue is that everything tries to load at once when you scroll, so scrolling is really slow. I thought what would happen is the imageview would just stay blank (or a placeholder) until the thread has loaded the appropriate image. I guess not though.
Thanks for any help.
Have a look at my answer to this question, it has a sample project which shows how to do it but downloading images from the net. You should be able to modify it quite easily to work for you getting images from the SD card.
I have an easy to use library under a basically public domain license that you can check out... It will cancel loading for rows that aren't displaying and uses two threads to do image loading.
You can check it out on my GitHub: https://github.com/tbiehn/Android-Adapter-Image-Loader