Android - GridView's onResume - android

I am developing Android apps,
once part of this apps is creating a GridView that contain some image (the image is loaded from URL),
then another activity that show the selected image in full screen will be appeared when one of image in GridView is onClick.
Problem:
When I enter the GridView activity, it takes some second to load all image in gridview normally.
Then I click one of image to enter the full screen activity and click back button to go back to GridView,
but, it takes some second to loading when go back to gridview, just like loading all image again.
I wonder why the gridview activity will loading for a few second when onResume?
For example, in Google Play, the full screen view of sample image in any apps can be back to previous view immediately.
Enclosed code:
GridView:
public class ManagePhoto extends Activity {
ImageAdapter ia;
GridView gridview;
InputStream inputStream;
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
TextView tvRunningMark;
boolean bRunning;
String[] purl;
Bitmap[] bm;
String the_string_response;
TouchImageView touch;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_manage);
//gv is Gobal Value
final Gvalue gv = ((Gvalue) getApplicationContext());
gridview = (GridView) findViewById(R.id.gv_photo);
gridview.setOnItemClickListener(new GridView.OnItemClickListener() {
public void onItemClick(AdapterView adapterView, View view,int position, long id) {
gv.setbm(bm[position]);
Intent myIntent = new Intent(adapterView.getContext(), FullScreenImage.class);
startActivityForResult(myIntent, 0);
}
});
new GridTask().execute();
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return purl.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some
// attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200,200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
try {
bm[position] = loadBitmap(purl[position]);
imageView.setImageBitmap(bm[position]);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return imageView;
}
}
class GridTask extends AsyncTask<Void, String, Void> {
#Override
protected void onPostExecute(Void result) {
gridview.setAdapter(ia);
final LinearLayout llo_probar = (LinearLayout)findViewById(R.id.llo_probar);
llo_probar.setVisibility(LinearLayout.GONE);
gridview.setVisibility(GridView.VISIBLE);
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(String... values) {
}
#Override
protected Void doInBackground(Void... params) {
getphoto();
bm = new Bitmap[purl.length];
ia = new ImageAdapter(ManagePhoto.this);
return null;
}
}
private Bitmap loadBitmap(String url) throws MalformedURLException,IOException {
return BitmapFactory.decodeStream(new FlushedInputStream(
(InputStream) new URL(url).getContent()));
}
class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(final InputStream inputStream) {
super(inputStream);
}
#Override
public long skip(final long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int bytesRead = read();
if (bytesRead < 0) { // we reached EOF
break;
}
bytesSkipped = 1;
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
public void getphoto(){
final Gvalue gv = ((Gvalue) getApplicationContext());
final TextView tv_fn = (TextView) findViewById(R.id.tv_fn);
String result = "";
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("sql",
("select * from personal_photo where member_id = " + gv.getuid())));
InputStream is = null;
// http post
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://" + gv.getserverIP()
+ "/android_getdata.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection " + e.toString());
}
// convert response to string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
Log.e("log_tag", "Error converting result " + e.toString());
}
// parse json data
try {
List url = new ArrayList();
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
url.add(json_data.getString("save_location"));
}
int size = url.size();
purl = new String[size];
for (int j = 0; j < size; j++) {
purl[j] = (String) url.get(j);
}
} catch (JSONException e) {
Log.e("log_tag", "Error parsing data " + e.toString());
}
}
public void toast(String text) {
Toast.makeText(ManagePhoto.this, text, 5).show();
}
}
Full screen:
public class FullScreenImage extends Activity {
TouchImageView touch;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
new ShowPhotoTask().execute();
}
class ShowPhotoTask extends AsyncTask<Void, String, Void> {
#Override
protected void onPostExecute(Void result) {
setContentView(touch);
}
#Override
protected void onPreExecute() {
setContentView(R.layout.full_image);
}
#Override
protected void onProgressUpdate(String... values) {
}
#Override
protected Void doInBackground(Void... params) {
final Gvalue gv = ((Gvalue) getApplicationContext());
touch = new TouchImageView(FullScreenImage.this);
touch.setMaxZoom(4f); // change the max level of zoom, default is 3f
touch.setImageBitmap(gv.getbm());
return null;
}
}
}

From your getView code in your ImageAdapter, everytime you will load the image from the internet again.
You should download the image to local, next time, when your set the image, you try to get it from local firstly.
As well you should put the get bitmap in the thread as you have putting the parse JSON in the thread.
Here is an demo, i think it will help you.

In your gridview onclick you are starting activity with startActivityForResults(intent,0); replace it with startActivity(intent);
also when you are finishing the FullScreenActivity just use finish();
might solve your problem

It's so slow because you don't perform your operations with background threads, caching..
A simple and better solution could be a collection that contains all your bitmaps inserted by AsyncTasks that you'll execute to download the pictures.
There are better solutions but they are more difficult to implement.
For example you can consider the possibility to keep a thread pool that resolves your runnables represented by "download the http://jhon.doe.jpg" and then "show now on the UI thread".

As you have written below function inside the getView() method:
bm[position] = loadBitmap(purl[position]);
I would say you should implement code to load Image Asynchronously. In this logic, image is synced in your memory card once its downloading is done. So next time it will load directly from memory card instead of loading it from web again.
Here is a code example you can give a try: Android - Universal Image Loader

Related

How to refresh GridView for Custom Image Adapter?

I am currently working on an online android learning project and am facing issue with refreshing my grid view.
My app displays a grid with several images initially. On click of the Refresh Button from the Menu, the GridView should be populated with the new images.Also,on click of any image, app goes to Detail Activity which shows the current image URL.
Currently I first populate the GridView with sample images, using my custom adapter & Picasso. Then an AsyncTask executes which gets the new image URLs from a JSON. This new imageURL List has to be fed to my adapter so that the grid displays the new images.
However, I am not able to accomplish this. My initial grid shows images and on click of these, I get their URL on detail activity screen as expected. However, when I click on the Refresh in the menu, I don't see the new images. I am trying to set the adapter with the updated URL array in the onPostExecute().
On click of the old image I see the new URL in the detail activity, however once I click back the image is still not updated and URL changes back to the old one. Sometimes when I scroll the new image shows up and then app crashes.
So the basic issue is that even after getting the new URLs, I am unable to populate the GridView with new images. Any help on this will be appreciated. Thanks,
Code Snippet:
public class MovieListFragment extends Fragment {
public CustomAdapter customAdapter;
public GridView gv;
public List<String> allImages=new ArrayList<String>();
public List<String> newImages=new ArrayList<String>();
public String LOG_TAG=MovieListFragment.class.getSimpleName();
public int abc=0;
public MovieListFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview= inflater.inflate(R.layout.movie_list_fragment, container, false);
//Fake Data Creation for 1st time GridView load.
allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
//Set Adapter
gv = (GridView) rootview.findViewById(R.id.gridview);
customAdapter=new CustomAdapter(getActivity(),allImages);
gv.setAdapter(customAdapter);
//On Click Listener
gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra("imageURL", allImages.get(position).toString());
startActivity(intent);
}
});
return rootview;
}
//My Custom Adapter
public class CustomAdapter extends BaseAdapter{
private Context mContext;
private List<String> myImageList;
public CustomAdapter(Context c, List<String> finalImageList) {
mContext = c;
myImageList=finalImageList;
notifyDataSetChanged();
}
#Override
public int getCount() {
return myImageList.size();
}
#Override
public Object getItem(int position) {
return myImageList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(500, 500));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
// imageView.setPadding(2, 2, 2, 2);
} else {
imageView = (ImageView) convertView;
}
Picasso.with(getActivity())
.load(myImageList.get(position))
.into(imageView);
return imageView;
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.movie_list_fragment_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id=item.getItemId();
if(id==R.id.action_refresh){
updateMovieList();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
private void updateMovieList() {
FetchMovieDetailsTask fetchMovieDetailsTask=new FetchMovieDetailsTask();
fetchMovieDetailsTask.execute("Popularity");
}
public class FetchMovieDetailsTask extends AsyncTask<String, Void, String[]>{
public String LOG_TAG_SECOND=FetchMovieDetailsTask.class.getSimpleName();
#Override
protected String[] doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieDetailJsonStr = "";
String filterType = "";
String api_key = "e77c4d231a4c24ffe0357b694751910c";
if (params[0].equals("Popularity")) {
filterType = "vote_average.desc";
} else if (params[0].equals("Rating")) {
filterType = "popularity.desc";
}
try {
final String MOVIEDETAIL_BASE_URL = "https://api.themoviedb.org/3/discover/movie?";
final String FILTER_PARAM = "sort_by";
final String APP_KEY_PARAM = "api_key";
Uri builtUri = Uri.parse(MOVIEDETAIL_BASE_URL).buildUpon()
.appendQueryParameter(FILTER_PARAM, filterType)
.appendQueryParameter(APP_KEY_PARAM, api_key).build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG_SECOND, builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieDetailJsonStr = buffer.toString();
Log.v(LOG_TAG_SECOND, " Movie Details JSON " + movieDetailJsonStr);
try {
getMovieDetailsFromJSON(movieDetailJsonStr);
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return null;
}
private String[] getMovieDetailsFromJSON(String movieDetailsJSON) throws JSONException{
final String MOV_TITLE = "title";
final String MOV_OVERVIEW = "overview";
final String MOV_RATING = "vote_average";
final String MOV_POSTER_PATH = "poster_path";
final String MOV_LIST = "results";
JSONObject movieListJSON = new JSONObject(movieDetailsJSON);
JSONArray movieListArray = movieListJSON.getJSONArray(MOV_LIST);
int numOfMovies=8;
allImages.clear();
String[] resultStrs = new String[numOfMovies];
String[] resultPosters= new String[numOfMovies];
for(int i=0; i<numOfMovies; i++){
String title;
String overview;
String rating;
String poster_path;
JSONObject movieDetails=movieListArray.getJSONObject(i);
overview=movieDetails.getString(MOV_OVERVIEW);
title=movieDetails.getString(MOV_TITLE);
rating=movieDetails.getString(MOV_RATING);
poster_path=movieDetails.getString(MOV_POSTER_PATH);
resultStrs[i]=title + "\n" + overview + "\n" + rating + "\n" + poster_path;
resultPosters[i]=poster_path;
makePosterURL(resultPosters[i]);
}
for (String s : resultStrs) {
Log.v(LOG_TAG_SECOND, "MOVIE DETAILS: " + s);
}
return resultStrs;
}
private void makePosterURL(String resultPoster) {
String baseURL="http://image.tmdb.org/t/p/w500";
//resultPoster=resultPoster.replace("\\", "");
String finalURL="";
finalURL=baseURL+resultPoster;
Log.v(LOG_TAG_SECOND, "Final Poster URL " + finalURL);
allImages.add(finalURL);
}
#Override
protected void onPostExecute(String[] strings) {
if(strings!=null){
customAdapter=new CustomAdapter(getActivity(), allImages);
gv.invalidateViews();
gv.setAdapter(customAdapter);
}
// super.onPostExecute(strings);
}
}
Because you always return null in your doInBackground() so the code never resets your adapter with the updated lits. To update your updater you just need to call
adapter.notifyDataSetChanged();
in your onPostExecuted()
btw, your getMovieDetailsFromJSON() return type String[] is useless the same as doInBackgound() and you should make it void as you don't use the value.

android AsyncTask and UI thread interaction

I'm using the AsyncTask to open a URL, access the server, fetch the content and display them in a list view in the main activity. The content extracted consists of a title of the newspaper and a URL to the website, which will be displayed on a WebView in a second activity, if a "read" button is clicked. I coded out the program straight away and it works, but when I looked back at it, I found something that seems unreasonable, so mainly I want to make clear how the code works. Here is the code for the main activity:
package com.example.newsapp;
public class MainActivity extends Activity {
static final private String LOG_TAG = "main";
private ArrayList<Content> aList;
private class Content{
Content() {};
public String title;
public String url;
}
private class MyAdapter extends ArrayAdapter<Content>{
int resource;
public MyAdapter(Context _context, int _resource, List<Content> titles) {
super(_context, _resource, titles);
resource = _resource;
// this.context = _context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout newView;
final Content content = getItem(position);
// Inflate a new view if necessary.
if (convertView == null) {
newView = new LinearLayout(getContext());
String inflater = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(inflater);
vi.inflate(resource, newView, true);
} else {
newView = (LinearLayout) convertView;
}
// Fills in the view.
TextView tv = (TextView) newView.findViewById(R.id.listText);
ImageButton b = (ImageButton) newView.findViewById(R.id.listButton);
b.setBackgroundResource(0);
tv.setText(content.title);
Typeface type = Typeface.createFromAsset(getAssets(),"LiberationSerif-BoldItalic.ttf");
tv.setTypeface(type);
// Sets a listener for the button, and a tag for the button as well.
b.setTag(Integer.toString(position));
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Reacts to a button press.
Intent intent = new Intent(MainActivity.this, WebPage.class);
Bundle bundle = new Bundle();
bundle.putString("URL", content.url);
intent.putExtras(bundle);
startActivity(intent);
}
});
return newView;
}
}
class MyAsyncTask extends AsyncTask<String, String, String> {
private ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
InputStream inputStream = null;
String result = "";
Content content;
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Downloading the news...");
progressDialog.show();
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
MyAsyncTask.this.cancel(true);
}
});
}
#Override
protected String doInBackground(String... params) {
String url_select = params[0];
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
try {
// Set up HTTP post
// HttpClient is more then less deprecated. Need to change to URLConnection
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// Read content & Log
inputStream = httpEntity.getContent();
} catch (UnsupportedEncodingException e1) {
Log.e("UnsupportedEncodingException", e1.toString());
e1.printStackTrace();
} catch (ClientProtocolException e2) {
Log.e("ClientProtocolException", e2.toString());
e2.printStackTrace();
} catch (IllegalStateException e3) {
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
} catch (IOException e4) {
Log.e("IOException", e4.toString());
e4.printStackTrace();
}
// Convert response to string using String Builder
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"), 8);
StringBuilder sBuilder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
result = sBuilder.toString();
} catch (Exception e) {
Log.e("StringBuilding & BufferedReader", "Error converting result " + e.toString());
}
return result;
} // protected Void doInBackground(String... params)
protected void onPostExecute(String result) {
//parse JSON data
try {
super.onPostExecute(result);
Log.i(LOG_TAG, result);
JSONObject object = new JSONObject(result);
JSONArray jArray = object.getJSONArray("sites");
for(int i=0; i < jArray.length(); i++) {
JSONObject jObject = jArray.getJSONObject(i);
content = new Content();
if (jObject.has("title") && jObject.has("url")){
content.title = jObject.getString("title");
content.url = jObject.getString("url");
aList.add(content);
aa.notifyDataSetChanged();
}
} // End Loop
progressDialog.dismiss();
} catch (JSONException e) {
// progressDialog.dismiss();
Log.e("JSONException", "Error: " + e.toString());
}
} // protected void onPostExecute(String result)
}
private MyAdapter aa;
private MyAsyncTask loadTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadTask = new MyAsyncTask();
loadTask.execute("http://luca-ucsc.appspot.com/jsonnews/default/news_sources.json");
aList = new ArrayList<Content>();
aa = new MyAdapter(this, R.layout.list_element, aList);
ListView myListView = (ListView) findViewById(R.id.listView1);
myListView.setAdapter(aa);
aa.notifyDataSetChanged();
}
public void refresh(View v){
if (loadTask.getStatus() == AsyncTask.Status.FINISHED){
aList.clear();
aa.notifyDataSetChanged();
new MyAsyncTask().execute("http://luca-ucsc.appspot.com/jsonnews/default/news_sources.json");
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
So you can see that only after loadTask.execute() in onCreate(), do I create the object for alist and aa, but I'm already using them in onPostExecute() in the AsyncTaks class, so I'm not very clear what happens here, because onPostExecute() and the UI are on the same thread, so the code in onPostExecute() should be executed first.
I thought I should put
aList = new ArrayList<Content>();
aa = new MyAdapter(this, R.layout.list_element, aList);
into onPostExecute(), which is more logical to me, but the app crashes this way. Also I think deleting aa.notifyDataSetChanged(); in onPostExecute() shouldn't be a problem because it's also in the onCreate() method, but this actually causes the list view to be blank, without any content. Actually, putting any of the codes after loadTask.execute() into the if block of the onPostExecute() method causes some problem, or crashes the app. That would be great if somebody can give some insight or hint. Thanks for reading.
onPostExecute is called on the UI thread after the background task completes its work. You cannot guarantee the timing of this call in relation to other calls on the UI thread.
Since you are already implementing getView yourself, I recommend you extend BaseAdapter instead of ArrayAdapter and implement the other few required methods. It's not hard and you can use whatever data structure you want to back the adapter. Assuming you use a List<Content> to back the adapter, you can write a method to swap the list in place like so:
public void swapList(List<Content> newList) {
this.list = newList;
notifyDataSetChanged();
}
In your AsyncTask, you have complete control of the Params, Progress, and Result parameterized types. They don't all have to be String. You can do this instead:
private class myAsyncTask extends AsyncTask<String, Void, List<Content>> {
/* ... */
}
The String for Params is the URL (same as you do now). Void for Progress because you don't publish progress anyway. List<Content> for Result because that's the thing you actually want to end up with after doing your task.
You should do ALL of your work in doInBackground. There is no reason to deserialize a String into a JSONArray and mess around with that in onPostExecute, particularly since that is happening on the main thread. Rewrite doInBackground to return a List<Content>, and all you need in onPostExecute is this:
public void onPostExecute(List<Content> result) {
adapter.swapList(result);
}
Now you can create the adapter once (in onCreate()) and just swap the list whenever it's appropriate.

Can I use AsyncTask inside ListFragment? or should I use AsyncTaskLoader?

I tried the code below and also tried the AsyncTaskLoader approach. The app crashes when I instantiate the AsyncTask. Pleas advise me on the best approach to load JSON in a list fragment inside tab host.
The code below is the tab fragment (I use action bar tabs in main activity):
public class TabTop extends ListFragment {
Context context = getActivity().getBaseContext();
String API_URL = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
ArrayList<Deal> deals;
DealsListAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
#SuppressWarnings("unused")
int a = 0;
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
GetTopDeals getTopDeals = new GetTopDeals(context);
getTopDeals.execute(API_URL);
super.onActivityCreated(savedInstanceState);
}
class GetTopDeals extends AsyncTask<String, Void, ArrayList<Deal>>{
ProgressDialog progressDialog;
public GetTopDeals(Context activity) {
this.progressDialog = new ProgressDialog(activity);
}
#Override
protected void onPostExecute(ArrayList<Deal> result) {
adapter = new DealsListAdapter(context, result);
setListAdapter(adapter);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
progressDialog.setCancelable(true);
progressDialog.setProgress(0);
progressDialog.setMessage("loading Top deals...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
super.onPreExecute();
}
#Override
protected ArrayList<Deal> doInBackground(String... urls) {
String response = sendRequest(urls[0]); // make request for json
return processResponse(response); // parse the Json and return ArrayList to postExecute
}
private String sendRequest(String apiUrl) {
BufferedReader input = null; // get the json
HttpURLConnection httpCon = null; // the http connection object
StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"
try {
URL url = new URL(apiUrl);
httpCon = (HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
return null;
}
input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
String line;
while ((line = input.readLine()) != null) {
response.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpCon != null) {
httpCon.disconnect();
}
}
return response.toString();
}
}
public ArrayList<Deal> processResponse(String response) {
try {
JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
deals = new ArrayList<Deal>();
for (int i = 0; i < results.length(); i++) { // in this loop i copy the json array to movies arraylist in order to display listView
JSONObject jMovie = results.getJSONObject(i);
int api_id = jMovie.getInt("id");
String name = jMovie.getString("title");
String content = jMovie.getString("synopsis");
JSONObject posters = jMovie.getJSONObject("posters");
String image_url = posters.getString("profile");
}
}catch (JSONException e) {
e.printStackTrace();
}
return deals;
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(getActivity().getBaseContext(), DealInformation.class);
startActivity(intent);
super.onListItemClick(l, v, position, id);
}
}
Make your asynctask in his own file.
And when your asynctask is finish, implement OnPostExecute which is automatically call. Notify your adapter by a notifyDataSetChanged like that :
#Override
protected void onPostExecute(List<NewItem> list) {
Adapter.getListe().clear();
Adapter.getListe().addAll(list);
Adapter.notifyDataSetChanged();
}
thank you guys,
i want to post my answer. after some research i decided to go with AsyncTaskLoader.
this is my code
public class TabOurPicks extends ListFragment implements LoaderCallbacks<String[]> {
// when activity loads- onActivityCreated() calls the initLoader() who activate onCreateLoader()
#Override
public void onActivityCreated(Bundle savedInstance) {
super.onActivityCreated(savedInstance);
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new String[]{}));
getLoaderManager().initLoader(0, null,this).forceLoad();
}
// onCreateLoader instantiate the asynctaskloaser who work in bg
#Override
public RSSLoader onCreateLoader(int arg0, Bundle arg1) {
return new RSSLoader(getActivity()); //
}
// after bg process invoke onLoadFinished() who work in ui thread
#Override
public void onLoadFinished(Loader<String[]> loader, String[] data) {
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, data
) );
}
#Override
public void onLoaderReset(Loader<String[]> arg0) {
// TODO Auto-generated method stub
}
and this is the inner class for the loader:
static public class RSSLoader extends AsyncTaskLoader<String[]>
{
public RSSLoader(Context context) {
super(context);
}
#Override
public String[] loadInBackground() {
String url = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
String response = sendRequest(url);
return processResponse(response);
}
private String sendRequest(String url) {
BufferedReader input = null; // get the json
HttpURLConnection httpCon = null; // the http connection object
StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"
try {
URL apiUrl = new URL(url);
httpCon = (HttpURLConnection) apiUrl.openConnection();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
return null;
}
input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
String line;
while ((line = input.readLine()) != null) {
response.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpCon != null) {
httpCon.disconnect();
}
}
return response.toString();
}
private String[] processResponse(String response) {
String[] deals = null;
try {
JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
deals = new String[10];
for (int i = 0; i < 9; i++) { // in this loop i copy the json array to movies arraylist in order to display listView
JSONObject jMovie = results.getJSONObject(i);
String name = jMovie.getString("title");
deals[i] = name;
}
}catch (JSONException e) {
e.printStackTrace();
}
return deals;
}
}
}
It doesn't matter if your asynctask has its own file. You just don't want your activity to extends asynctask as this would make your activity asynchronous - but this is impossible to do anyways due to java's double inheritance rule.
Based on the architecture of your app and your programming style the asyntask can be an inner class in the activity. on the PostExecute method make sure you have given data to your adapter and that the adapter is set to the list, then just run notifyDataSetChanged().
Assuming your asynctask is loading data from cache or the network you are on the right track with your approach to this.

image display as gridview

i want to display images from mysql server(testing in localhost) using imageurl,i have images in a filder on my server,in an android client app as gridview along with text.how do i use imageurl in my code?
mymainmenu.java
public class MainMenu extends Activity {
GridView gridView;
static final String[] MOBILE_OS = new String[] {
"Android", "iOS","Windows", "Blackberry" };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainmenu_list);
gridView = (GridView) findViewById(R.id.gridView1);
gridView.setAdapter(new ImageAdapter(this, MOBILE_OS));
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(
getApplicationContext(),
((TextView) v.findViewById(R.id.grid_item_label))
.getText(), Toast.LENGTH_SHORT).show();
}
});
}
}
my imageadapter.java:
public class ImageAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
public ImageAdapter(Context context, String[] mobileValues) {
this.context = context;
this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
// get layout from list.xml
gridView = inflater.inflate(R.layout.list, null);
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.grid_item_label);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.grid_item_image);
String mobile = mobileValues[position];
if (mobile.equals("Windows")) {
imageView.setImageResource(R.drawable.imggrid);
} else if (mobile.equals("iOS")) {
imageView.setImageResource(R.drawable.imggrid);
} else if (mobile.equals("Blackberry")) {
imageView.setImageResource(R.drawable.imggrid);
} else {
imageView.setImageResource(R.drawable.imggrid);
}
} else {
gridView = (View) convertView;
}
return gridView;
}
#Override
public int getCount() {
return mobileValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}
I dnt know how to use the following in my code:
try {
URL url = new URL(imageFileURL);
URLConnection conn = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection)conn;
httpConn.setRequestMethod("GET");
httpConn.connect();
if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = httpConn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
img.setImageBitmap(bitmap);
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Put the image downloading code in a AsyncTask. Here is the explanation.
Execute one instance of asynctask in your getView method, i.e to fetch one image everytime.
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView mImageView;
public void setImageView(ImageView img) {
mImageView = img;
}
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
Call task.setImageView(yourImageViewinGrid) before executing your AsyncTask to let it know where to set the image after downloading.
To get the image, you have to do something like :
URL new_url = new URL("your url");
Bitmap image_bitmap = BitmapFactory.decodeStream(newurl.openConnection() .getInputStream()); ImageView image_view = new ImageView(this);
image_view.setImageBitmap(image_bitmap);
Anyway, it's better to download the image as background task. What I actually do is to create a custom view with one private inner class that extend AsyncTask to download the image for you.
I dnt know how to use the following in my code:
that code will download the image for you, you can place in separate thread either AsyncTask or Thread and set the downloaded image in the imageview... simple as that. There are so many example on the web you can google it out
EIDTED
code to download the image
public class AsyncFetchImage extends AsyncTask<String, Void, Bitmap>{
private WeakReference<ImageView> imageReference;
// private WeakReference<Dialog> dialogReferance;
public AsyncFetchImage(ImageView imageview) {
imageReference = new WeakReference<ImageView>(imageview);
// dialogReferance = new WeakReference<Dialog>(dialog);
}
#Override
protected Bitmap doInBackground(String... s) {
return downloadImage(s[0]);
}
private Bitmap downloadImage(String url) {
final AndroidHttpClient client = AndroidHttpClient.newInstance("Nixit");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if(statusCode != HttpStatus.SC_OK){
Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if(entity != null){
InputStream is = null;
try{
is = entity.getContent();
final Bitmap bit = BitmapFactory.decodeStream(is);
return bit;
}finally{
if(is != null)
is.close();
entity.consumeContent();
}
}
} catch (IOException e) {
e.printStackTrace();
return null;
} finally{
if(client != null){
client.close();
}
}
Log.i("Image Fetch","Image Fetch Complete");
return null;
}
#Override
protected void onPostExecute(Bitmap result) {
if(isCancelled()){
result = null;
}
if(imageReference != null){
ImageView imageView = imageReference.get();
// Dialog di = dialogReferance.get();
if (imageView != null) {
imageView.setImageBitmap(result);
// di.show();
}
}
}
}
How to use:-
imageView = (ImageView)dialog.findViewById(R.id.imageView1);
AsyncFetchImage fetchImage = new AsyncFetchImage(imageView);
fetchImage.execute(url);
You can use this in getview method of adapter
Hope that help

android:load images from url and show in gridview

i am making an app in which i have to get response from xml and i get image urls .Now i want to put images from urls into gridview but i dnt know how to extract images from urls and put in gridview.Any help will be appreciated.My code is as follows:
public class GalleryNewActivity extends Activity {
private ProgressDialog dialog;
GridView ga;
Element e;
Node elem;
public List<Drawable> pictures;
ImageView imageView;
static final String PREFS_NAME = "MyPrefs";
static final String USER_KEY = "user";
static final String Name = "name";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if(isNetworkconn()){
new GetSPCAsyncTask().execute("");
}else{
showDialogOnNoInternet();
}
ga = (GridView)findViewById(R.id.Gallery01);
ga.setAdapter(new ImageAdapter(this));
imageView = (ImageView)findViewById(R.id.ImageView01);
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return pictures.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) { // if it's not recycled, initialize some
// attributes
LayoutInflater li = getLayoutInflater();
v = li.inflate(R.layout.galleryitem, null);
imageView = (ImageView)v.findViewById(R.id.thumbImage);
imageView.setLayoutParams(new GridView.LayoutParams(200, 250));
// imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(2, 5, 2, 5);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageDrawable(pictures.get(position));
imageView.setTag(pics[position]);
return imageView;
}
private class GetPicsToNextPage extends AsyncTask<String, String, String>{
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dialog = ProgressDialog.show(GalleryNewActivity.this, "Please wait", "Loading...");
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String str = null;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
dialog.dismiss();
Intent intent = new Intent(getApplicationContext(), Flip3d.class);
startActivity(intent);
}
}
private boolean isNetworkconn(){
ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (conMgr.getActiveNetworkInfo() != null && conMgr.getActiveNetworkInfo().isAvailable() && conMgr.getActiveNetworkInfo().isConnected()) {
return true;
}else{
return false;
}
}
private void showDialogOnNoInternet(){
AlertDialog.Builder alt_bld = new AlertDialog.Builder(GalleryNewActivity.this);
alt_bld.setTitle("Error.");
alt_bld.setMessage("Your phone is not connected to internet.");
alt_bld.setCancelable(false);
alt_bld.setNeutralButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
alt_bld.show();
}
//loader for dynamic starts
private class GetSPCAsyncTask extends AsyncTask<String, String, String>{
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dialog = ProgressDialog.show(GalleryNewActivity.this, "Please wait", "Loading...");
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
String xml = XMLfunctions.getXML();
Document doc = XMLfunctions.XMLfromString(xml);
NodeList nodes = doc.getElementsByTagName("Image");
for (int i = 0; i < nodes.getLength(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
e = (Element)nodes.item(i);
//map.put("Image", XMLfunctions.getValue(e, "Image"));
map.put("ImagePath", "Naam:" + XMLfunctions.getValue(e, "ImagePath"));
map.put("ImageHeadline", "Headline: " + XMLfunctions.getValue(e, "ImageHeadline"));
System.out.println(map.put("ImageHeadline", "Headline: " + XMLfunctions.getValue(e, "ImageHeadline")));
map.put("ImageDesc", "Desc: " + XMLfunctions.getValue(e, "ImageDesc"));
System.out.println(map.put("ImageDesc", "Desc: " + XMLfunctions.getValue(e, "ImageDesc")));
mylist.add(map);
Drawable d=LoadImageFromWebOperations();
pictures.add(d);
}
return xml;}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
dialog.dismiss();
}
private Drawable LoadImageFromWebOperations()
{
String path=XMLfunctions.getValue(e, "ImagePath");
try{
InputStream is = (InputStream) new URL(path).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
Log.w("CREADO","CREADO");
return d;
}catch (Exception e) {
System.out.println("Exc="+e);
return null;
}
}
}
}
I would suggest you to check below solutions for loading images from URL:
Android - Universal Image loader by Nostra
Lazy load of images in ListView
Result you can get if you use Universal image loader:
call this function with url you will get Drawable , and then store this drawables into custom class and then place in grid view.
call function like this
ImageOperations(this, imageurl)
public Object fetch(String address) throws MalformedURLException, IOException {
URL url = new URL(address);
Object content = url.getContent();
return content;
}
private Drawable ImageOperations(Context ctx, String url) {
try {
InputStream is = (InputStream) this.fetch(url);
Drawable d = Drawable.createFromStream(is, "src");
return d;
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
}
https://github.com/koush/UrlImageViewHelper
UrlImageViewHelper will fill an ImageView with an image that is found at a URL.
The sample will do a Google Image Search and load/show the results asynchronously.
UrlImageViewHelper will automatically download, save, and cache all the image urls the BitmapDrawables. Duplicate urls will not be loaded into memory twice. Bitmap memory is managed by using a weak reference hash table, so as soon as the image is no longer used by you, it will be garbage collected automatically.
else use this,
public static Bitmap loadBitmap(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;
}

Categories

Resources