I would like to load a large/complex svg image file into my imageView. Loading the svg takes time to load on my HTC Desire S and Lenovo a60. About 5 Second and 10 seconds respectively.
Right now my app becomes unresponsive for about 5 seconds until the imageView is fully loaded
I load the image using this simple code..
svg = SVGParser.getSVGFromResource(getResources(), R.raw.gf);
mImageView.setImageDrawable(svg.createPictureDrawable());
I was looking something like (webView)
webView.setWebViewClient(new WebViewClientEx(MainActivity.this, DEBUG) {
#Override
public void onPageFinished(final WebView view, String url) {
...........
.............}
});
which I used in my previous project...
Finally my questions:
1.) What is the best approach to make the app look responsive?
I was planning to use asynctask but don't know how to use it... Is it applicable here?
2.) Is there listener after the image is fully loaded?
My approach here is to show the progressDialog by the time I load the imageView and hide it after the imageView has fully loaded.
another other suggestions which you think is better to use for showing/hiding progressDialog ? Thanks!
Use an async task here. (a Loader would work aswell but async task is a bit easier to explain.)
private class LoadSVGTask extends AsyncTask<Integer, Void, Drawable> {
protected Drawable doInBackground(Integer... res) {
mProgressBar.setVisibility(View.Visible);
svg = SVGParser.getSVGFromResource(getResources(),res);
Drawable d = svg.createPictureDrawable();
return d;
}
// gets executed in main thread
protected void onPostExecute(Drawable result) {
mProgressBar.setVisibility(View.Gone);
mImageView.setImageDrawable(result);
}
}
Launch the Task with:
new LoaderSVGTask().execute(R.raw.gf, null, null);
see: http://developer.android.com/reference/android/os/AsyncTask.html
Just refer AsyncTask in that
protected void onPreExecute (){
progressDialog.show(......);
}
protected abstract Result doInBackground (Params... params){
//load your image from here
}
protected void onPostExecute (Result result){
progressDialog.dismiss();
}
Related
I want to use Glide to eagerly download images and cache them on disk for a future use. I want to call this functionality from a background thread.
I've read Glide's caching documentation, but it doesn't explain how to download the image without having an actual target right now. Then I found this issue and tried to use a similar approach, but whatever I try I get this exception:
java.lang.IllegalArgumentException: You must call this method on the main thread
So, how can I tell Glide to cache an image from a background thread?
EDIT: I really want to call Glide's methods on background thread. I know that I can use Handler and other ways to offload it to UI thread, but that's not what I'm asking.
GlideApp.with(context)
.downloadOnly()
.diskCacheStrategy(DiskCacheStrategy.DATA) // Cache resource before it's decoded
.load(url)
.submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get() // Called on background thread
If want to load images in cache for future use in background thread then Glide have this functionality
here how you can do this
//here i passing application context so our glide tie itself with application lifecycle
FutureTarget<File> future = Glide.with(getApplicationContext()).downloadOnly().load("your_image_url").submit();
now if you want to retrieve the saved path that you want to store in your DB then you can do
File file = future.get();
String path = file.getAbsolutePath();
you can also do this in just one line returning a path string like this
String path = Glide.with(getApplicationContext()).downloadOnly().load("your_image_url").submit().get().getAbsolutePath();
You must call this method on the main thread
Wherever you call a method to use Glide or doing something from background, run inside:
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here, use glide or do your things on UiThread
}
});
To use it inside the main thread and then error should be gone.
Did I get the question right?
private class update extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
try {
RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL) // Saves all image resolution
.centerCrop()
.priority(Priority.HIGH)
.placeholder(R.drawable.null_image_profile)
.error(R.drawable.null_image_profile);
Glide.with(context).load(imageUrl)
.apply(options);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
//finish
}
}
I am running following operations in the background thread:
Store byte image data locally as a jpeg.
Fetch that image as a bitmap.
Run face-detection algorithm and fetch facial points
Place an overlay according to those points
And finally save that bitmap again.
While performing these operations, I am displaying a progress bar. But the progress bar animation gets stuck i.e it becomes unresponsive until the thread completes its work(update: nothing in the whole UI seems to function while the background work is running).
Doesn't this make actual intentions of using background thread obsolete?
What approach should I take to overcome this problem?
My code is:
//Show ProgressBar
Runnable worker = () -> {
//My Operations
runOnUiThread(() -> {
//Hide ProgressBar
});
}
You can use the async approach, it will work
private class MyAsyncTask extends AsyncTask<String, Progress, Bitmap> {
protected void onPreExecute() {
// Runs on the UI thread before doInBackground
progressBar.setVisibility(ProgressBar.VISIBLE);
}
protected Bitmap doInBackground(String... strings) {
// Some long-running task like downloading an image.
// convert your bitmap
return someBitmap;
}
protected void onProgressUpdate(Progress... values) {
//update progress
}
protected void onPostExecute(Bitmap result) {
//hide progress bar
}}
I am working on android app and i have a images slider in my app,now i want to when i click on my slider image,the images are display in another activity but it takes a little time while to open,now i want to implement and add a loading progress bar when display the image in another activity,can anyone tell me how i can implement progress bar when i click my image slider and when open another activity it's start progressbar and when images are display it's dimiss?any help,idea and sugession will be much appreciated,Thanks in advance.
This is my activity when i click on my image and anothe activity open:
iv_openimage = (ImageView) findViewById(R.id.iv_openimage);
iv_openimage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(VarientDetails.this,ImageSwitcher.class);
intent.putExtra("imageurls", imageurls);
Log.d("CMH", "images url = " + imageurls);
startActivity(intent);
}
});
and this is my imageswitcher activity were i can display my images:
public class ImageSwitcher extends Activity {
ImageView iv_getimage;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.imageswitcher);
iv_getimage = (ImageView) findViewById(R.id.imageView1);
ArrayList<String> resultArray = getIntent().getStringArrayListExtra("imageurls");
Log.d("CMH imgswtchr", "images url = " + resultArray);
Picasso.with(getBaseContext()).load(resultArray.get(0))
.into(iv_getimage);
}
}
What you want to do is put the resource intensive tasks in a so called AsyncTask. This AsyncTask runs on a different thread then the UI thread. Put it can do UI operations in it's onPostExecute();
So what you want is to do something along the lines of:
start activity
set progressbar visible
start asynctask
In the AsyncTask:
execute image task that takes up time
hide progressbar
For more info about AsyncTask you can go here: http://developer.android.com/reference/android/os/AsyncTask.html
Also, the reason that your current implementation isn't optimal is because it all runs on the same thread. This makes the UI thread unavailable at a certain time. This is bad practice, and gives the user a bad experience. So I'd always recommend using an AsyncTask for operations like this. While it is possible to show the progressbar before and after the task is done, the task would still lock the UI thread.
Edit
As requested, here is something I'd do in your situation:
I'd first create an inner class that extends AsyncTask like this
private class ImageLoadTask extends AsyncTask<String, Param, String>
{
#Override
protected String doInBackground(String... params)
{
//do something to retrieve the images
}
#Override
protected void onPostExecute(String result)
{
//hide the progressbar
}
}
Then in the Activity itself to start this AsyncTask simply do:
progressBar.setVisibility(View.Visible);
ImageLoadTask imgTask = new ImageLoadTask();
imgTask.execute("parameter");
I've found a lot of posts explaining how to load images inside a ListView using AsyncTask, the problem is that all, at least the ones I have found, do it by instantiating and starting an AsyncTask every single time the getView method is called inside the ListView adapter.
I've done this already, all works well, but when I go through the ListView really quickly, it throws an exception at .execute saying that it refuses to create anymore threads.
So my question is how to overcome this issue while at the same time keep using AsyncTasks ? (I could use a single, "normal, Java" Thread but the project specifications say I'm not allowed.
Thanks and cheers
I found this very usefull:
class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
// params comes from the execute() call: params[0] is the url.
return downloadBitmap(params[0]);
}
#Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
see the complete post here
I would go for Aquery for Android
aq.id(R.id.image1).image("http://www.vikispot.com/z/images/vikispot/android-w.png");
Learn more: android-query - ImageLoading
or Volley:
Volley: Easy, Fast Networking for Android
You should rather use IntentService instead of AsyncTask and also cache the images you already downloaded so next time no data needs to be fetched. Or you can take a look at existing projects like SmartImageView that should do all you need
I have been struggling with this problem for many days. please help me..
In my android application i am trying to download images from remote server dynamically ( no of images dynamically come ). for downloading all images it is taking 30 to 40 seconds mean time user has to wait to see the activity . But it is the worst case that loading activity after loading all images. I want to load activity first then load images one by one.
Is there anything to do it?
Thanks and Regards,
Kiran
I think you need to implemet your code using "AsyncTask", for more info, refer this link: http://developer.android.com/reference/android/os/AsyncTask.html
for example:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
See in above example, Write your code for downloading images inside "doInBackground()" function and write the code for displaying iamges inside "onPostExecute()" function.
Enjoy!!