Am develop the Frame application. For that i want to display images(frames) from url. the url has more than 50 images. For that i use gridview but it lacks some points such as,
1.It speeds very slow to load images.
2.We declare the name and size of the images at code time so that we dont add images to the url after publishing the applicaton.
I need solution for these asap. Please anyone give me suggestion.
Use below link of lazy loading listview, this will help you.
Lazy Loading ListView
Use Above link Code and Add another activity and another layout for display selected image, if u have any issue than tell me, i will put full code here.
1.It speeds very slow to load images.
It will depend on You bandwidth and device Cache.
2. We declare the name and size of the images at code time so that we dont add images to the url after publishing the application.
You can have predefine URL so at code time you can append the image name to url.and once you have URL ready using AsyncTask download images one by one \
The below snippets will help you.
DownloadHelper.java
public interface DownloadHelper
{
public void OnSucess(Bitmap bitmap);
public void OnFailure(String response);
}
MainActivity.java
public class GalleryExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
DownloadHelper downloadHelper = new DownloadHelper()
{
#Override
public void OnSucess(Bitmap bitmap)
{
ImageView imageView=(ImageView)findViewById(R.id.imageView);
imageView.setImageBitmap(bitmap);
}
#Override
public void OnFailure(String response)
{
Toast.makeText(context, response, Toast.LENGTH_LONG).show();
}
};
new MyTask(this,downloadHelper).execute("image url");
}
MyTask.java
public class DownloadTask extends AsyncTask<String, Integer, Object>
{
private Context context;
private DownloadHelper downloadHelper;
private ProgressDialog dialog;
public DownloadTask(Context context,DownloadHelper downloadHelper)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
dialog = new ProgressDialog(context);
dialog.setTitle("Please Wait");
dialog.setMessage("Fetching Data!!");
dialog.setCancelable(false);
dialog.show();
super.onPreExecute();
}
#Override
protected Object doInBackground(String... params)
{
URL aURL = new URL(myRemoteImages[position]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
return bm;
}
#Override
protected void onPostExecute(Object result)
{
dialog.dismiss();
if (result != null)
{
downloadHelper.OnSucess((Bitmap)result);
}
else
{
downloadHelper.OnFailure("Error in Downloading Data!!");
}
super.onPostExecute(result);
}
}
Related
I am currently using an AsyncTask to fetch the JSON array when pressing a button. After that i have another button called ParseJson which opens a new activity in which a list is shown with the JSONArray.
What i would like, is to have one button instead of 2, but since the getJSON button (first button above) is starting a backgroundtask which needs to be finnished first, before launching the other activity (ParseJSON button), this doesnt work in one button right now.
I heard something about using a loading dialog, but i am quite new to this and have no idea how to solve it.
This is the code i use, but i also need the the value from the Textview in the background task. I will send the value of the textview to a php file (by POST) which fetches the data from the database.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void getJSON(View view) {
TextView txv = (TextView) findViewById(R.id.orderID);
txv.getText().toString;
//I need this value in the backgroundtask later
new BackgroundTask().execute();
}
class BackgroundTask extends AsyncTask<Void, Void, String>
{
String json_url = "MYJSONURL";
String JSON_STRING;
#Override
protected String doInBackground(Void... params) {
try {
URL url = new URL(json_url);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
while ((JSON_STRING = bufferedReader.readLine())!=null)
{
stringBuilder.append(JSON_STRING+"\n");
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
return stringBuilder.toString().trim();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
json_string = result;
}
}
public void parseJSON(View view)
{
if(json_string==null)
{
Toast.makeText(getApplicationContext(), "First Get JSON", Toast.LENGTH_LONG).show();
}
else
{
Intent intent = new Intent(this, DisplayListView.class);
intent.putExtra("json_data", json_string);
startActivity(intent);
}
}
Instead of starting the AsyncTask by a button press you code in a way by which it can be started as soon as your main activity is launched. Use onProgressUpdate method of the AsyncTask which will show some progress, once that method is finished your data is loaded. Then you use one button to parse and display the data in the list.
You may refer this to know more about AsyncTask methods
You can have a look at the below code to understand how communication can happen between an activity and AsyncTask. For simplicity I have a count loop running inside AsyncTask which will update the progress on the activity.
Please be warned that this code communicates with the same activity which started the AsyncTask. So, if you would like to perform any such background task, you should be having the AsyncTask attached to your second activity.
public class MainActivity extends Activity {
private ProgressBar mProgress;
private int mProgressStatus = 0;
TextView percentage = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgress = (ProgressBar) findViewById(R.id.progress_bar);
percentage = (TextView) findViewById(R.id.percentage);
new CountProgress().execute();
}
class CountProgress extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
mProgress.setProgress(0);
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... unused) {
for (int i=0; i<101;i++ ) {
if (isCancelled())
break;
publishProgress(i);
SystemClock.sleep(200);
}
return(null);
}
#Override
protected void onProgressUpdate(Integer... progress) {
if (!isCancelled()) {
mProgress.setVisibility(View.VISIBLE);
// updating progress bar value
mProgress.setProgress(progress[0]);
// updating progess percentage text
percentage.setText(progress[0].toString() + "%");
}
}
#Override
protected void onPostExecute(Void unused) {
Toast.makeText(getApplicationContext(), R.string.done, Toast.LENGTH_SHORT).show();
}
}
}
A full working app code can be downloaded from here and you can extend it further for your needs.
I am using Picasso for my image handling and use it to download images from a backend server and save to the local device. I use Target to save the image
Picasso.with(context)
.load(url)
.into(target);
Since the target code gets a bitmap, I have to use bitmap.compress() to write the image to local disk and I use JPEF format with quality of 100 assuming this will preserve the original quality.
Reading this it seems like this might not be what I want. In one case, the image on the backend was 90kb and the image that was written was 370kb. The original image can be generated using an arbitrary quality value. What is the easiest way to save the image using Picasso without the size/quality changing?
Target target = new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
}
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom arg1) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
FileOutputStream out = null;
try {
out = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onPostExecute(Void info) {
}
}.execute();
}
#Override
public void onBitmapFailed(Drawable arg0) {
}
};
UPDATE: more elegant solution here: https://github.com/square/picasso/issues/1025#issuecomment-102661647
Solved the problem using this solution.
In my PagerAdapter's instantiateItem() method, I run an AsyncTask that will download the image, save it to a file and then call Picasso with that image file.
PagerAdapter instantiateItem():
RemoteImageToImageViewAsyncTask remoteImageToImageViewAsyncTask =
new RemoteImageToImageViewAsyncTask(imageView, url, imagePath);
remoteImageToImageViewAsyncTask.execute();
RemoteImageToImageViewAsyncTask
public class RemoteImageToImageViewAsyncTask extends AsyncTask<Void, Void, Void> {
ImageView imageView;
String url;
File output;
public RemoteImageToImageViewAsyncTask(ImageView imageView, String url, File output) {
this.imageView = imageView;
this.url = url;
this.output = output;
}
#Override
protected Void doInBackground(Void... params) {
// Downloads the image from url to output
ImageDownloader.download(url, output);
return null;
}
#Override
protected void onPostExecute(Void params) {
Picasso.with(context)
.load(output)
.into(imageView);
}
}
I am trying to load an image in my imageview but it does not load any image for the link.
The link has the image but I still get empty blank space.
private class LoadImage extends AsyncTask<String, String, Bitmap> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected Bitmap doInBackground(String... args) {
try {
String url = "http://www.learn2crack.com/wp-content/uploads/2014/04/node-cover-720x340.png";
URL urlurl = new URL(url);
bitmap = BitmapFactory.decodeStream(urlurl.openConnection().getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
protected void onPostExecute(Bitmap image) {
if(image != null){
img.setImageBitmap(image);
}else{
Toast.makeText(activity.getApplicationContext(), "Image Does Not exist or Network Error", Toast.LENGTH_SHORT).show();
}
}
}
XML
<ImageView
android:id="#+id/list_image"
android:layout_width="50dip"
android:layout_height="50dip"
/>
As you can see in the logcat stacktrace you have a network on mainthread exception becasue you are doing a network task on the 'main' thread which is also called the gui thread. You need to use an AsyncTask for this.
private class DownloadImageTask extends AsyncTask<Object, Void, Bitmap> {
#Override
protected Bitmap doInBackground(Object... args) {
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
return bmp;
}
#Override
protected void onPostExecute(Bitmap result) {
//here do stuff with your bitmap data, also here you can interact with the gui
}
}
Also I recommend using an Image downloading library to download images off the web. They make it really easy to download images and you dont have to worry a lot about the tiny details.
I have some problem with AsyncTask in my application.
There is AsyncTask which takes File from sd card and makes operations with it.
It is actually giving me a proper result, but while doing the task there are a black screen and a blocked user interface about 3 seconds that obviously would make a user annoyed. I'm wondering how to get rid of this problem.
So here is the code:
ParseXMLTask.java:
public ParseXMLTask(Context context, IPostParse iPostParse, ProgressBar progressBar) {
this.context = context;
this.iPostParse = iPostParse;
this.progressBar = progressBar;
}
#Override
protected Intent doInBackground(File... params) {
File file = params[0];
Intent pack = new Intent(context, PackActivity.class);
/* some heavy parsing task */
return pack;
}
#Override
protected void onPreExecute() {
progressBar.setIndeterminate(true);
}
#Override
protected void onPostExecute(Intent result) {
iPostParse.postParse(result);
}
LoadingActivity.java:
The executing task code:
private void parseXML() {
File file = new File(PATH + fileName + ".xml");
ParseXMLTask parseTask = new ParseXMLTask(this, this, loadingBar);
parseTask.execute(file);
}
And the implemented method of the interface, nothing special:
public void postParse(Intent result) {
result.putExtra("name", packName);
result.putExtra("author", packAuthor);
result.putExtra("date", packDate);
result.putExtra("file", fileName);
result.putExtra("votes", votes);
startActivity(result);
}
Hope you help me to solve this problem, thanks!
This can happen if you are putting too much data into your Intent's extras.
This is my AsyncTask, called from getView of an adapter:
class LoadImage extends AsyncTask<Object,Void,String>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
}
Bitmap userAvatarStream = null ;
Bitmap IconStream = null;
URL IconURL;
ProgressDialog dialog;
#Override
protected void onPreExecute(){
//Setting all the variables by getting the ids from the layout
return;
}
#Override
protected String doInBackground(Object... params) {
try {
IconURL = new URL(cr.ImageUrl);
IconStream = BitmapFactory.decodeStream(IconURL.openConnection().getInputStream());
}
catch (MalformedURLException e){
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result){
// ImageView user_avatar = (ImageView)v.findViewById(R.id.follower_user_avatar);
imv.setImageBitmap(IconStream);
return;
}
The problem that I get here is that the images keep loading. Lets say I scroll down and the images go away to be refreshed again if I scroll up the list. It keeps making calls to get the images. This behaviour is obviously undesirable except at one place that if the internet on your cell-phone goes down and comes up again, this would help to auto-load the images. But, in the current state even that is crashing as it keeps making calls. How to stop AsyncTask from doing that?
Just cache you images to filesystem or memory.
Each time you scroll the list getView is called. If you put the image loading method on getView and didn't use Image Caching then it'll download the images again and again. There are some opensource image loader for list with caching support.
One of them is droidFu. It supports two level of caching. Filesystem and memory. Get droidFu from following link.
https://github.com/kaeppler/droid-fu
Try a boolean flag to keep the check whether the image was loaded successfully or not.
If it was not then only make a call to Load Image Asynctask.
You may need to use a boolean array to keep the track if there are more than one row in adapter.
Try this code:
class performBackgroundTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog.setMessage("Please wait ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... arg0) {
callxmlparser();
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (ringtoneNamelist != null && ringtoneNamelist.size() > 0) {
songslist.setAdapter(new Songslist());
} else {
Toast.makeText(SongsList.this,"Network signal speed is too slow\ncannot parse the data from the server\n Please try again", Toast.LENGTH_LONG).show();
}
dialog.dismiss();
}
}