I seem to have a problem with my ImageAdapter. It should update a GridView but does not do it.
Code:
public class MainActivityFragment extends Fragment {
ImageAdapter imageAdapter;
GridView gridView;
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
gridView = (GridView) rootView.findViewById(R.id.gridView);
imageAdapter = new ImageAdapter(getActivity(),new ArrayList<Movie>());
gridView.setAdapter(imageAdapter);
return rootView;
}
#Override
public void onStart() {
super.onStart();
UpdateMovies();
}
private void UpdateMovies() {
FetchMoviesTask task = new FetchMoviesTask();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
String sort = preferences.getString(getString(R.string.pref_sort_key), getString(R.string.pref_sort_default));
task.execute(sort);
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Movie> data;
public ImageAdapter(Context c, ArrayList<Movie> movies) {
mContext = c;
data = movies;
}
public int getCount() {
return data.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) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
View gridView;
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
gridView = new GridView(mContext);
gridView = inflater.inflate(R.layout.grid_item_poster, null);
imageView = (ImageView)gridView.findViewById(R.id.poster);
} else {
imageView = (ImageView) convertView;
}
if (data.size() != 0) {
Log.v("IMAGE_ADAPTER","SetView= " + data.get(position).poster);
Picasso.with(mContext).load(data.get(position).poster).into(imageView);
}
return imageView;
}
public void updatePosters(ArrayList<Movie> newMovies) {
data.clear();
data.addAll(newMovies);
this.notifyDataSetChanged();
}
}
public class FetchMoviesTask extends AsyncTask<String, Void, ArrayList<Movie>> {
private final String LOG_TAG = FetchMoviesTask.class.getName();
private ArrayList<Movie> getMovieDataFromJson(String movieJsonStr, int numDays)
throws JSONException {
// These are the names of the JSON objects that need to be extracted.
final String MOV_LIST = "results";
final String MOV_ID = "id";
final String MOV_TITLE = "original_title";
final String MOV_OVERVIEW = "overview";
final String MOV_RATING = "vote_average";
final String MOV_DATE = "release_date";
final String MOV_POSTER = "poster_path";
JSONObject listJson = new JSONObject(movieJsonStr);
JSONArray movieArray = listJson.getJSONArray(MOV_LIST);
ArrayList<Movie> movies = new ArrayList<>();
for(int i = 0; i < movieArray.length(); i++) {
int id;
String title;
String overview;
String rating;
String date;
String poster;
// Get the JSON object representing the day
JSONObject movie = movieArray.getJSONObject(i);
id = movie.getInt(MOV_ID);
title = movie.getString(MOV_TITLE);
overview = movie.getString(MOV_OVERVIEW);
rating = movie.getString(MOV_RATING);
date = movie.getString(MOV_DATE);
poster = movie.getString(MOV_POSTER);
Movie newMovie = new Movie(id, title, overview, rating, date, poster);
movies.add(newMovie);
}
for (Movie s : movies) {
Log.v(LOG_TAG, "Movie entry: " + s.print());
}
return movies;
}
#Override
protected void onPostExecute(ArrayList<Movie> result) {
if(result != null){
Log.v(LOG_TAG,"DATA SET CHANGED! SIZE= " + result.size());
imageAdapter.updatePosters(result);
}
}
#Override
protected ArrayList<Movie> doInBackground(String... params) {
if(params.length == 0){
return null;
}
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieJsonStr = null;
String format = "JSON";
String units = "metric";
String apiKey = "********************";
int numDays = 7;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
final String MOVIE_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
final String SORT_PARAM = "sort_by";
final String DESC = ".desc";
final String API_PARAM = "api_key";
Uri builtUri = Uri.parse(MOVIE_BASE_URL).buildUpon()
.appendQueryParameter(SORT_PARAM,(params[0]+DESC))
.appendQueryParameter(API_PARAM,apiKey)
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
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) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
Log.v(LOG_TAG,"Movie JSON String: " + movieJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
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);
}
}
}
try {
return getMovieDataFromJson(movieJsonStr, numDays);
}catch (JSONException e){
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
}
}
fragment_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivityFragment">
<GridView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/gridView"
android:columnWidth="180dp"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"/>
grid_item_poster.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:scaleType="centerCrop"
android:id="#+id/poster"
android:adjustViewBounds="true">
</ImageView>
The strange thing is that when I add a ArrayList with elements when I create my ImageAdapter in onCreateView, it does work but when I leave that list unpopulated it does not update.
Anyone got any clue what to do?
Been searching for the solution the whole day now. :D
Thanks in advance.
I have weird impression that something is wrong with your getView() method - I can be wrong but try this one:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
ImageView imageView;
if (convertView == null) {
convertView = inflater.inflate(R.layout.grid_item_poster, null);
imageView = (ImageView) convertView.findViewById(R.id.poster);
convertView.setTag(imageView);
} else {
imageView = (ImageView) convertView.getTag();
}
if (data.size() != 0 && data.get(position) != null) {
Log.v("IMAGE_ADAPTER","SetView= " + data.get(position).poster);
Picasso.with(mContext).load(data.get(position).poster).into(imageView);
} else {
//I think that you should reset image when there is a issue with data set
imageView.setImageResource(-1);
}
return imageView;
}
Moreover this comment - create a new ImageView for each item referenced by the Adapter is invalid because adapter reuse views, which are outside of the screen, so sometimes instead of creating new instance of ImageView, list displays old one with new data
Edit
Try to create new data list instead of cleaning old one:
public void updatePosters(ArrayList<Movie> newMovies) {
data = new ArrayList<Movies>();
data.addAll(newMovies);
this.notifyDataSetChanged();
}
You getView is not correctly implemented. Firs of all it is very weird what you are trying to achieve there, you are inflating something just to get an ImageView from that layout. You could instead instantiate the ImageView inside the method:
public View getView(int position, View convertView, ViewGroup parent) {
View view=convertView;
if (view == null) {
view=new ImageView(mContext);
view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout
.LayoutParams.MATCH_PARENT,LinearLayout
.LayoutParams.WRAP_CONTENT));
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
final String url=data.get(position).poster;
if (!TextUtis.isEmpty(url) {
Log.v("IMAGE_ADAPTER","SetView= " + url);
Picasso.with(mContext).load(url).into(((ImageView)view));
} else {
Picasso.with(mContext).load(android.R.color.transparent).into(((ImageView)view);
}
return view;
}
Related
I am using ...
GUARDIAN_REQUEST_URL = http://content.guardianapis.com/search?from-date=2015-01-01&order-by=newest&show-fields=thumbnail&q=android&api-key=test
... to parse JSON data. My app runs perfectly, but I want to change the color of different sectionName for e.g. for Technology = pink, for Society = blue. Below is the screenshot of the app. Can anyone tell me how to change color of different sections?
NewsAdapter.java:
public class NewsAdapter extends ArrayAdapter<News> {
Context mContext;
public NewsAdapter(Context context, ArrayList<News> news) {
super(context, 0, news);
mContext = context;
}
// "view holder" that holds references to each subview
private class ViewHolder {
private final ImageView newsImage;
private final TextView sectionName;
private final TextView webTitle;
public ViewHolder(ImageView newsImage, TextView sectionName, TextView webTitle) {
this.newsImage = newsImage;
this.sectionName = sectionName;
this.webTitle = webTitle;
}
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
News currentNews = getItem(position);
// Check if there is an existing view (called convertView) that we can reuse,
// otherwise, if convertView is null, then inflate a new list item layout.
if (convertView == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
convertView = layoutInflater.inflate(R.layout.news_list_item, null);
final ImageView newsImage = (ImageView) convertView.findViewById(R.id.image_view);
final TextView sectionName = (TextView) convertView.findViewById(R.id.section_name);
final TextView webTitle = (TextView) convertView.findViewById(R.id.web_title);
final ViewHolder viewHolder = new ViewHolder(newsImage, sectionName, webTitle);
convertView.setTag(viewHolder);
}
final ViewHolder viewHolder = (ViewHolder) convertView.getTag();
Picasso.with(mContext)
.load(currentNews.getThumbnail())
.resize(100, 120)
.into(viewHolder.newsImage);
viewHolder.sectionName.setText(currentNews.getSectionName());
viewHolder.webTitle.setText(currentNews.getWebTitle());
return convertView;
}
}
QueryUtils.java:
public class QueryUtils {
public QueryUtils() {
}
/**
* Query the GUARDIAN dataset and return a list of {#link News} objects.
*/
public static List<News> fetchNewsData(String requestUrl) {
// Create URL object
URL url = createUrl(requestUrl);
// Perform HTTP request to the URL and receive a JSON response back
String jsonResponse = null;
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
e.printStackTrace();
}
// Extract relevant fields from the JSON response and create a list of {#link News}s
List<News> newses = extractFeatureFromjson(jsonResponse);
return newses;
}
/**
* Returns new URL object from the given string URL.
*/
private static URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return url;
}
/**
* Make an HTTP request to the given URL and return a String as the response.
*/
private static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(1000);
urlConnection.setConnectTimeout(1500);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
}
} catch (IOException e){
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// Closing the input stream could throw an IOException, which is why
// the makeHttpRequest(URL url) method signature specifies than an IOException
// could be thrown.
inputStream.close();
}
}
return jsonResponse;
}
/**
* Convert the {#link InputStream} into a String which contains the
* whole JSON response from the server.
*/
private static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
/**
* Return a list of {#link News} objects that has been built up from
* parsing the given JSON response.
*/
private static List<News> extractFeatureFromjson(String newsJson) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(newsJson)) {
return null;
}
// Create an empty ArrayList that we can start adding news to
List<News> newses = new ArrayList<>();
try {
JSONObject baseJsonResponse = new JSONObject(newsJson);
JSONObject response = baseJsonResponse.getJSONObject("response");
JSONArray newsArray = response.getJSONArray("results");
for (int i = 0; i < newsArray.length(); i++) {
JSONObject currentNews = newsArray.getJSONObject(i);
String sectionName = currentNews.getString("sectionName");
Log.e("SECTION_NAME", sectionName);
String webTitle = currentNews.getString("webTitle");
Log.e("WEB_TITLE", webTitle);
String webUrl = currentNews.getString("webUrl");
Log.e("WEB_URL", webUrl);
JSONObject fields = currentNews.getJSONObject("fields");
if (fields.has("thumbnail")) {
String thumbnail = fields.getString("thumbnail");
Log.e("THUMBNAIL", thumbnail);
News news = new News(thumbnail, sectionName, webTitle, webUrl);
newses.add(news);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return newses;
}
}
news_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/cv"
android:layout_width="170dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:id="#+id/image_view"
android:layout_width="140dp"
android:layout_height="200dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"/>
<TextView
android:id="#+id/section_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:background="#color/colorAccent"
android:padding="5dp"
android:textSize="9sp"
android:textColor="#android:color/white"
tools:text="technolgy"/>
<TextView
android:id="#+id/web_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/black"
android:layout_marginTop="#dimen/activity_horizontal_margin"
tools:text="Amazon and Google fight crucial battle over voice recognition" />
</LinearLayout>
</android.support.v7.widget.CardView>
You can change color based on your sectioned by the below changge:
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
News currentNews = getItem(position);
if(currentNews.getSectionName().equals("Technology"))
{
viewHolder.sectionName.setBackgroundResource(R.color.yourColor);
}
// Check if there is an existing view (called convertView) that we can reuse,
// otherwise, if convertView is null, then inflate a new list item layout.
if (convertView == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
convertView = layoutInflater.inflate(R.layout.news_list_item, null);
final ImageView newsImage = (ImageView) convertView.findViewById(R.id.image_view);
final TextView sectionName = (TextView) convertView.findViewById(R.id.section_name);
final TextView webTitle = (TextView) convertView.findViewById(R.id.web_title);
final ViewHolder viewHolder = new ViewHolder(newsImage, sectionName, webTitle);
convertView.setTag(viewHolder);
}
final ViewHolder viewHolder = (ViewHolder) convertView.getTag();
Picasso.with(mContext)
.load(currentNews.getThumbnail())
.resize(100, 120)
.into(viewHolder.newsImage);
viewHolder.sectionName.setText(currentNews.getSectionName());
viewHolder.webTitle.setText(currentNews.getWebTitle());
return convertView;
}
Switch case for color change :
switch (currentNews.getSectionName()) {
case "Technology":
viewHolder.sectionName.setBackgroundResource(R.color.yourColor);// change color
break;
default:
throw new IllegalArgumentException("Invalid Color Set " + currentNews.getSectionName());
}
Best way to do this is small change in json format
{
"id": "technology/shortcuts/2017/jan/24/how-apps-plan-to-conquer-your-mobile-phones-lockscreen-",
"type": "article",
"sectionId": "technology",
"sectionName": "Technology",
"color": "#FFC0CB",
"webPublicationDate": "2017-01-24T18:49:06Z",
"webTitle": "How apps plan to conquer your phone's lock screen",
"webUrl": "https://www.theguardian.com/technology/shortcuts/2017/jan/24/how-apps-plan-to-conquer-your-mobile-phones-lockscreen-",
"apiUrl": "https://content.guardianapis.com/technology/shortcuts/2017/jan/24/how-apps-plan-to-conquer-your-mobile-phones-lockscreen-",
"fields": {
"thumbnail": "https://media.guim.co.uk/e30bdc920d576ce623441d999535159c0af8c201/0_255_4632_2778/500.jpg"
},
"isHosted": false
}
Check color field in json #FFC0CB this is pink hex code
One of the Advantages of this is you can change color you want without touching or modifying APK file
And you can set this like
final ViewHolder viewHolder = (ViewHolder) convertView.getTag();
Picasso.with(mContext)
.load(currentNews.getThumbnail())
.resize(100, 120)
.into(viewHolder.newsImage);
viewHolder.sectionName.setText(currentNews.getSectionName());
viewHolder.webTitle.setText(currentNews.getWebTitle());
convertView.setBackgroundColor(Color.parseColor(currentNews.getColor()));
When I implement the GridView in the Fragment instead of the MainActivity class and after I run the app on my phone, the screen is blank. The app fetches the data from the server correctly but does not show anything on the mobile screen.
Here is my MainActivityFragment class :
public class MainActivityFragment extends Fragment {
private GridView gridView;
private GridViewAdapter gridAdapter;
private ArrayList<ImageItem> data;
public MainActivityFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
data = new ArrayList<>();
gridView = (GridView) rootView.findViewById(R.id.gridView);
gridAdapter = new GridViewAdapter(getActivity(), R.layout.grid_poster, data);
gridView.setAdapter(gridAdapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onStart() {
super.onStart();
FetchPosterTask posterTask = new FetchPosterTask();
posterTask.execute();
}
public class FetchPosterTask extends AsyncTask<Void, Void, Integer> {
private final String LOG_TAG = FetchPosterTask.class.getSimpleName();
private Integer parseResult(String result)
throws JSONException{
JSONObject response = new JSONObject(result);
JSONArray movies = response.getJSONArray("results");
ImageItem item = new ImageItem();
for (int i = 0; i < movies.length(); i++) {
JSONObject movie = movies.optJSONObject(i);
item = new ImageItem();
String posterPath = movie.getString("poster_path");
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("image.tmdb.org")
.appendPath("t")
.appendPath("p")
.appendPath("w185");
String poster = builder.toString()+posterPath;
item.setImage(poster);
Log.v(LOG_TAG, "poster_path " + poster);
}
data.add(item);
return 1;
}
#Override
protected Integer doInBackground(Void... params) {
Integer result = 0;
HttpURLConnection urlConnection = null;
String moviesJasonStr = null;
String sort_by = "popularity.desc";
BufferedReader reader = null;
try {
final String baseUrl = "http://api.themoviedb.org/3/discover/movie?";
final String QUERY_PARAM = "sort_by";
final String APPID_PARAM = "api_key";
Uri builtUri = Uri.parse(baseUrl).buildUpon()
.appendQueryParameter(QUERY_PARAM, sort_by)
.appendQueryParameter(APPID_PARAM, BuildConfig.OPEN_MOVIES_API_KEY)
.build();
URL url = new URL(builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
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) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
moviesJasonStr = buffer.toString();
Log.v(LOG_TAG, "moviesJasonStr: " + moviesJasonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
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);
}
}
}
try {
return parseResult(moviesJasonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Integer integer) {
Log.v(LOG_TAG, "result_integer: " + integer);
if (integer == 1) {
gridAdapter.setGridData(data);
} else {
Toast.makeText(getActivity(), "Failed to fetch data!", Toast.LENGTH_SHORT).show();
}
}
}
}
This is my GridViewAdapter class :
public class GridViewAdapter extends ArrayAdapter<ImageItem> {
private Context context;
private int layoutResourceId;
private ArrayList<ImageItem> data = new ArrayList<ImageItem>();
public GridViewAdapter(Context context, int layoutResourceId, ArrayList<ImageItem> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
/**
* Updates grid data and refresh grid items.
* #param data
*/
public void setGridData(ArrayList<ImageItem> data) {
this.data = data;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.image = (ImageView) row.findViewById(R.id.image);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
ImageItem item = data.get(position);
//holder.image.setImageBitmap(item.getImage());
Picasso.with(context).load(item.getImage()).into(holder.image);
return row;
}
static class ViewHolder {
ImageView image;
}
}
and this is my fragment_main.xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f0f0f0"
tools:context = ".MainActivityFragment">
<GridView
android:id="#+id/gridView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:columnWidth="100dp"
android:drawSelectorOnTop="true"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="5dp"
android:focusable="true"
android:clickable="true"/>
</RelativeLayout>
First of all return rootView in onCreate
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
data = new ArrayList<>();
gridView = (GridView) rootView.findViewById(R.id.gridView);
gridAdapter = new GridViewAdapter(getActivity(), R.layout.grid_poster, data);
gridView.setAdapter(gridAdapter);
return rootView;
}
and if its not working then set adapter in onPostexecute
you only has fragment,but fragment need activity to host,you can change this codepublic class MainActivityFragment extends Fragment to public class MainActivityFragment extends FragmentActivity
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.
I'm new to making android apps. I'm trying to make a simple app that pulls movie data from themoviedb.org and displays the posters from the movie on the main page. I'm using GridView and ImageView with a custom adapter but the screen shows up blank. I'm not sure what I need to do to get the images to show up.
Custom adapter:
public class CustomImageAdapter extends BaseAdapter {
private Context mContext;
private String[] inputs;
private List<ImageView> imageList;
LayoutInflater inflater;
public CustomImageAdapter(Context c, String[] inputs) {
mContext = c;
this.inputs = inputs;
inflater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return inputs.length;
}
public Object getItem(int position) {
return imageList.get(position);
}
public long getItemId(int position) {
return position;
}
public void add(String[] results) {
inputs = results;
imageList = new ArrayList<ImageView>();
for (int i = 0; i < inputs.length; i++){
ImageView imageView = new ImageView(mContext);
Picasso.with(mContext)
.load(inputs[i])
.into(imageView);
imageList.add(imageView);
}
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(mContext);
convertView = inflater.inflate(R.layout.grid_layout, null);
ImageView imageView = (ImageView) gridView.findViewById(R.id.grid_layout_image_view);
imageView = imageList.get(position);
} else {
gridView = (View) convertView;
}
return gridView;
}
}
Main Fragment:
public class GridFragment extends Fragment {
private static ImageView imageView;
private static String[] jsonStringHolder = new String[1];
private static CustomImageAdapter customImageAdapter;
private static GridView gridView;
public GridFragment() {
}
#Override
public void onStart() {
super.onStart();
FetchMovieTask fetchMovieTask = new FetchMovieTask();
fetchMovieTask.execute();
}
private void loadImageView(String[] result) {
try {
getMovieDataFromJson(result);
} catch (JSONException e) {
Log.e("LOG_TAG", e.getMessage(), e);
e.printStackTrace();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
//customImageAdapter = new CustomImageAdapter(getContext(), null);
gridView = (GridView) rootView.findViewById(R.id.grid_view);
//gridView.setAdapter(customImageAdapter);
return rootView;
}
private void getMovieDataFromJson(String[] jsonStringHolder)
throws JSONException {
final String OWM_POSTER_PATH = "poster_path";
final String OWM_RESULTS = "results";
String movieJsonStr = jsonStringHolder[0];
JSONObject movieJsonObject = new JSONObject(movieJsonStr);
JSONArray movieJsonArray = movieJsonObject.getJSONArray(OWM_RESULTS);
String[] resultStrs = new String[movieJsonArray.length()];
for (int i = 0; i < movieJsonArray.length(); i++) {
JSONObject movieDescriptionJsonObject = movieJsonArray.getJSONObject(i);
String posterPathPlaceholder =
movieDescriptionJsonObject.getString(OWM_POSTER_PATH);
final String FORECAST_BASE_URL =
"http://api.themoviedb.org/3/movie/";
final String SIZE = "w185";
resultStrs[i] = FORECAST_BASE_URL + SIZE + posterPathPlaceholder;
}
customImageAdapter = new CustomImageAdapter(getContext(), null);
customImageAdapter.add(resultStrs);
gridView.setAdapter(customImageAdapter);
}
public class FetchMovieTask extends AsyncTask<Void, Void, String[]> {
private final String LOG_TAG = FetchMovieTask.class.getSimpleName();
#Override
protected String[] doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieJsonStr = null;
// String format = "json";
//String units = "metric";
//int numDays = 7;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
final String FORECAST_BASE_URL =
"http://api.themoviedb.org/3/movie/";
final String PREFERENCE = "now_playing?";
final String API_KEY = "api_key=e0cbb327025cf835dfc53ca51d11db68";
//final String UNITS_PARAM = "units";
//final String DAYS_PARAM = "cnt";
String urlString = FORECAST_BASE_URL + PREFERENCE + API_KEY;
URL url = new URL(urlString);
// Create the request to OpenWeatherMap, and open the connection
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) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error pits", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
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);
}
}
}
String[] movieJsonStrArray = new String[1];
movieJsonStrArray[0] = movieJsonStr;
return movieJsonStrArray;
}
#Override
protected void onPostExecute(String[] result) {
if (result != null) {
jsonStringHolder[0] = result[0];
}
loadImageView(result);
}
}
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivityFragment">
<GridView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/grid_view"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true">
</GridView>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grid_layout_image_view" />
</RelativeLayout>
if you are trying to fill a list with rows, and you are new to android, perhaps, you should try extending from ListActivity or FragmentList, see the google guide at http://developer.android.com/guide/topics/ui/layout/listview.html , ListActivity and FragmentList are helper clases, they have a method "setListAdapter" that do the trick.
I am working on an app which performs (in an AsyncTask) a query to a remote server obtaining a JSON string.
To show the data on my ListView i have extended an ArrayAdapter.
When i execute my app, from the LogCat i can see that data is retrieved correctly but not shown in the ListView.
The only way i have to make everything work (and data be shown on the ListView) is by running the app in Debug mode, set a breakpoint on the line
myListView.setAdapter(myAdapter);
wait for a couple seconds and then resume the application.
After this procedure, everything works correctly.
Why is this happening?
Is the AsyncTask the right way for such a long operation, or should I use some other approach (but i don't know which one!).
Here is the MainActivity code
public class MainActivityFragment extends Fragment {
private List<Station> stationList = new ArrayList<Station>();
private StationAdapter stationsAdapter;
private ProgressDialog pd;
private String LOG_TAG = "ProvaAsyncTask";
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mioAsync mioTask = new mioAsync();
mioTask.execute();
stationsAdapter = new StationAdapter(stationList, getActivity());
ListView stationsListView = (ListView) rootView.findViewById(R.id.miaListView);
stationsListView.setAdapter(stationsAdapter);
return rootView;
}
public class mioAsync extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Creo la ProgressDialog che precede il caricamento dei dati
pd = new ProgressDialog(getActivity());
pd.setMessage(MainActivityFragment.this.getString(R.string.preloader_stations_list));
pd.show();
}
#Override
protected Void doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String forecastJsonStr = null;
try {
URL url = new URL("*remoteserver*");
// Create the request to the server, and open the connection
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;
}
forecastJsonStr = buffer.toString();
} 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);
}
}
}
try{
getStationsListFromJson(forecastJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
pd.dismiss();
}
private void getStationsListFromJson(String stationsJsonStr) throws JSONException {
JSONArray stationsArray = new JSONArray(stationsJsonStr);
String nomeStaz;
String numSat;
stationList.clear();
for (int i = 0; i < stationsArray.length(); i++) {
JSONObject j = stationsArray.optJSONObject(i);
Iterator it = j.keys();
while (it.hasNext()) {
String n = it.next().toString();
numSat = j.getString(n) + " stazioni";
n = it.next().toString();
nomeStaz = j.getString(n);
stationList.add(new Station(nomeStaz, numSat));
}
}
}
}
}
The JSON string i get in return is like this
[{"nome":"Station1","satelliti":"11"},{"nome":"Station2","satelliti":"9"},{"nome":"Station3","satelliti":"8"}]
Here is where i extend the ArrayList
public class StationAdapter extends ArrayAdapter<Station> {
private List<Station> stationsList;
private Context context;
public StationAdapter(List<Station> lista, Context cont){
super(cont, R.layout.listitems, lista);
this.stationsList = lista;
this.context = cont;
}
public int getCount() {
return stationsList.size();
}
public Station getItem(int position) {
return stationsList.get(position);
}
public long getItemId(int position) {
return stationsList.get(position).hashCode();
}
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
StationHolder holder = new StationHolder();
// controllo che il convertview non sia null
if (convertView == null){
// This a new view we inflate the new layout
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listitems, null);
// Now we can fill the layout with the right values
TextView stationName = (TextView) v.findViewById(R.id.testataUno);
TextView satellitesNumber = (TextView) v.findViewById(R.id.testataDue);
holder.stationNameView = stationName;
holder.satellitesNumberView = satellitesNumber;
v.setTag(holder);
} else {
holder = (StationHolder) v.getTag();
}
Station p = stationsList.get(position);
holder.stationNameView.setText(p.getName());
holder.satellitesNumberView.setText("" + p.getSatellites());
return v;
}
/* *********************************
* We use the holder pattern
* It makes the view faster and avoid finding the component
* **********************************/
private static class StationHolder {
public TextView stationNameView;
public TextView satellitesNumberView;
}
}
Here is the Station code
public class Station {
private String name;
private String satellites;
public Station(String nome, String satelliti){
this.name = nome;
this.satellites = satelliti;
}
public String getName(){
return this.name;
}
public String getSatellites(){
return this.satellites;
}
public void setName(String nome){
this.name = nome;
}
public void setSatellites(String satelliti){
this.satellites = satelliti;
}
}
You got the flow broken. It works in debug mode only because you stop execution of UI thread on your breakpoint, but line before your breakpoint you fired AsyncTask, and as this is not stopped, it downloads the data while you enjoy your breakpoint. You most likely assumed that AsyncTask (which is abbreviation of Asynchronous Task) is... well... synchronous. It's not. Your main code will not wait for asynctask,it will start it and continue. You need to rework your code and in asynctask's onPostExecute() method update your dataset based on downloaded content and then call notifyDatasetChanged() on your list's adapter. That should trigger list refresh.