[EDIT: Was able to solve this by passing a blank image to the list array on fragment load]
I am working on an app where grid views are refreshed dynamically fetching data from API. My gridview is not refrishing on load. The refresh is happening on clicking other options (like sort) or by just changing orientation in the app. How do I get it to refresh on load. I have tried calling the refresh function from onStart(), onCreate() and onCreateView() but it isn't working.
Github: https://github.com/abhrajitmukherjee/PopularMovies
Main code:
public class MainActivityFragment extends Fragment {
private ImageAdapter mImageAdapter;
public ArrayList<String[]> mThumbIds;
private GridView gridview;
public MainActivityFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment_main, menu);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.v("Initiate","Starts here-------------------");
updateMovieThumbs(getString(R.string.base_uri_popular));
gridview = (GridView) getActivity().findViewById(R.id.gridview);
mImageAdapter = new ImageAdapter(getActivity());
gridview.setAdapter(mImageAdapter);
updateMovieThumbs(getString(R.string.base_uri_popular));
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Intent intent = new Intent(getActivity(), MovieDetailsActivity.class)
.putExtra(getString(R.string.intent_poster_path), mThumbIds.get(position)[0])
.putExtra(getString(R.string.intent_title),mThumbIds.get(position)[1])
.putExtra(getString(R.string.intent_overview),mThumbIds.get(position)[2])
.putExtra(getString(R.string.intent_vote_avg),mThumbIds.get(position)[3])
.putExtra(getString(R.string.intent_release_date),mThumbIds.get(position)[4]);
startActivity(intent);
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_toprated) {
updateMovieThumbs(getString(R.string.base_uri_toprated));
} else if (id == R.id.action_popular) {
updateMovieThumbs(getString(R.string.base_uri_popular));
}
return true;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, container, false);
mThumbIds = new ArrayList<String[]>();
return v;
}
#Override
public void onStart() {
super.onStart();
}
private void updateMovieThumbs(String sortType) {
FetchMovieDatabase movieTask = new FetchMovieDatabase();
movieTask.execute(sortType);
Log.v("getCount", "Get Main count=" + Integer.toString(mThumbIds.size()));
}
public class FetchMovieDatabase extends AsyncTask<String, Void, ArrayList<String[]>> {
private final String LOG_TAG = FetchMovieDatabase.class.getSimpleName();
private ArrayList<String[]> getMovieDataJson(String movieJsonStr)
throws JSONException {
final String RESULTS = "results";
final String ORIGINAL_TITLE="original_title";
final String POSTER="poster_path";
final String OVERVIEW="overview";
final String VOTES="vote_average";
final String RELEASE="release_date";
ArrayList<String[]> newThumbids=new ArrayList<String[]>();
JSONObject movieJson = new JSONObject(movieJsonStr);
JSONArray movieArray = movieJson.getJSONArray(RESULTS);
for (int i = 0; i < movieArray.length(); i++) {
JSONObject results = movieArray.getJSONObject(i);
String posterPath = getString(R.string.api_image_base_path)+results.getString(POSTER);
String title=results.getString(ORIGINAL_TITLE);
String overview=results.getString(OVERVIEW);
String voteAvg=results.getString(VOTES);
String releaseDate=results.getString(RELEASE);
String[] outputAttr={posterPath,title,overview,voteAvg,releaseDate};
Log.v(LOG_TAG, posterPath);
newThumbids.add(outputAttr);
Log.v(LOG_TAG, Integer.toString(newThumbids.size()));
}
return newThumbids;
}
#Override
protected ArrayList<String[]> doInBackground(String... params) {
if (params.length == 0) {
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String movieJsonStr = null;
try {
final String BASE_URL = params[0];
final String API_KEY = "api_key";
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendQueryParameter(API_KEY, BuildConfig.MOVIES_API_KEY)
.build();
URL url = new URL(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) {
return null;
}
movieJsonStr = 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 {
return getMovieDataJson(movieJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ArrayList<String[]> result) {
if (result != null) {
if (mThumbIds.size()>0){
mThumbIds.clear();
}
mThumbIds = (ArrayList<String[]>) result.clone();
Log.v(LOG_TAG, "Postexecute count:"+Integer.toString( mThumbIds.size()));
mImageAdapter.notifyDataSetChanged();
}
}
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
Log.v("getCount", "Get Count=" + Integer.toString(mThumbIds.size()));
// return 5;
return mThumbIds.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) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setAdjustViewBounds(true);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
} else {
imageView = (ImageView) convertView;
}
Picasso.with(getActivity()).load(mThumbIds.get(position)[0]).into(imageView);
return imageView;
}
}
}
Related
I am taking an online course and making an android application for my self learning. In this application I want to show thumbnails of movie posters in a gridView. Now my question is how can I pass my movies arrayList to custom adapter from asyncTask. Is there something I can achieve in onPostExecute method. I mean how can I set data source for my adapter asynchronously in onPostExecute method of asyncTask?
here is my code.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FetchMovies mMovies = new FetchMovies(this);
mMovies.execute("popularity.desc");
GridView gridView= (GridView) findViewById(R.id.gridview);
gridView.setAdapter(new CustomAdapter(this,new ArrayList<MovieContract>()));
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(MainActivity.this, "" + position,
Toast.LENGTH_SHORT).show();
}
});
}}
public class CustomAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<MovieContract> movie_list;
public CustomAdapter(Context context, ArrayList<MovieContract> movie_list) {
mContext = context;
this.movie_list= movie_list;
}
#Override
public int getCount() {
return movie_list.size();
}
#Override
public MovieContract getItem(int position) {
return movie_list.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) {
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setPadding(8, 8, 8, 8);
Picasso.with(mContext).load("http://image.tmdb.org/t/p/w500/" + movie_list.get(position).getMovie_poster()).into(imageView);
} else {
imageView = (ImageView) convertView;
}
// imageView.setImageResource(mThumbIds[position]);
return imageView;
}}
public class FetchMovies extends AsyncTask<String,Void,ArrayList<MovieContract>> {
private CustomAdapter customAdapter;
private Context context;
private ArrayList<MovieContract> mMovie_list = new ArrayList<>();
private MovieContract mMovieContract;
private String poster_path;
public final String LOG_Tag=FetchMovies.class.getSimpleName();
public FetchMovies(Context context) {
this.context = context;
}
#Override
protected ArrayList doInBackground(String[] params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String MoviesJsonStr = null;
String Api_key= "xxxxxxxxxxxxxxxxxxxxxx";
try {
final String Movies_base="http://api.themoviedb.org/3/discover/movie?";
final String Sort_param="sort_by";
final String ApiKey_param="api_key";
final String Image_Size="w500";
Uri MovieUriBuilder=Uri.parse(Movies_base).buildUpon()
.appendQueryParameter(Sort_param,params[0])
.appendQueryParameter(ApiKey_param, Api_key)
.build();
Log.v(LOG_Tag, "URI Builder" + MovieUriBuilder.toString());
URL url= new URL(MovieUriBuilder.toString());
urlConnection=(HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream= urlConnection.getInputStream();
StringBuffer buffer= new StringBuffer();
if(inputStream==null){
MoviesJsonStr=null;
}
reader= new BufferedReader(new InputStreamReader(inputStream));
String Result;
while ((Result=reader.readLine())!=null){
buffer.append(Result + '\n');
}
if (buffer.length() == 0) {
MoviesJsonStr = null;
}
MoviesJsonStr = buffer.toString();
Log.v(LOG_Tag,"Forecast Jason String " + MoviesJsonStr);
}
catch (IOException e){
Log.e("FetchMovies", "Error ", e);
MoviesJsonStr=null;
}
finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
try {
return ParseMoviesJsonString(MoviesJsonStr);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
private ArrayList<MovieContract> ParseMoviesJsonString(String movieJsonStr ) throws JSONException{
final String json_result="results";
final String json_poster_path="poster_path";
final String json_original_title="original_title";
final String json_title="title";
final String json_releaseDate="release_date";
final String json_overview="overview";
final String json_vote_average="vote_average";
ArrayList<MovieContract> movie_list= new ArrayList<>();
JSONObject MovieJson = new JSONObject(movieJsonStr);
JSONArray MovieArray = MovieJson.getJSONArray(json_result);
String[] resultStrs = new String[MovieArray.length()];
for(int i = 0; i < MovieArray.length(); i++) {
//JSONObject Movieobject = MovieArray.getJSONObject(i);
JSONObject result_movie=MovieArray.getJSONObject(i);
MovieContract movie = new MovieContract();
movie.setTitle(result_movie.getString(json_original_title));
movie.setMovie_poster(result_movie.getString(json_poster_path));
movie.setPlot_synopsis(result_movie.getString(json_overview));
movie.setRelease_date(result_movie.getString(json_releaseDate));
movie.setVote_average(result_movie.getString(json_vote_average));
movie_list.add(movie);
}
for (MovieContract result : movie_list){
Log.v(LOG_Tag," preparing data " + result.getMovie_poster() + " " +result.getPlot_synopsis() );
}
return movie_list;
}
#Override
protected void onPostExecute(ArrayList<MovieContract> Movie_list) {
}}
Declare a your CustomAdapter as an instance variable in the activity:
private CustomAdapter customAdapter;
Create the Adapter and set the RecyclerView adapter this way:
customAdapter = new CustomAdapter(this,new ArrayList<MovieContract>());
gridView.setAdapter(customAdapter);
Create an update data method for your CustomAdapter:
public void updateMovies(ArrayList<MovieContract> movie_list) {
this.movie_list= movie_list;
}
Then in onPostExecute:
customAdapter.updateMovies(movie_list);
customAdapter.notifyDataSetChanged();
I always do this to make async task more usable
create an Object in your async task class
OnResult onresult;
in your Async task create an interface
public interface OnResult{
public void onfinishprogress(ArrayList<> resultlist);
}
//create a method in async task
public void setOnResult(OnResult onresult)
{
this.onresult=onresult;
}
in your onPostExecute(..) set the result
onPostExecute(ArrayList<MovieContract> Movie_list){
if(this.onresult!=null)
this.onresult.onfinishprogress(Movie_list);
}
now come how to get the result in MainActivity
FetchMovies fmv=FetchMovies();
fmv.execute(url);
//now get the result from the interface created above
fmv.setOnResult(new OnResult(){
onfinishprogress(ArrayList<> resultlist)
{
//here you get the resultlist which you passed up there.
gridView.setAdapter(customAdapter);
}
});
I am developing app just like YOUTUBE. I am getting data from the server and showing it in listview. Because data is too big so i want to restrict list view to 5 items and then when I scroll down to the bottom of listview it should add 5 more item.
I am calling ASyncTask from fragment
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
view = layoutInflater.inflate(R.layout.tab_fragment_2, container, false);
listView = (ListView) view.findViewById(R.id.myList);
New.jsonAsyncTask.execute("my url select_video.php?");
}
Now I have separate JsonAsyncTask Class because I am calling it from 3 fragments just like above mentioned way..
public class JSONAsyncTask extends AsyncTask<String, String, List<SetDatails>> {
ListView listView1;
Context context1;
List<SetDatails> videoLiast1;
private static int tab_id;
public JSONAsyncTask(ListView listView, List<SetDatails> videoLiast,Context context,int id) {
this.listView1 = listView;
this.context1 = context;
this.videoLiast1 = videoLiast;
tab_id=id;
}
#Override
protected List<SetDatails> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader myReader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream myInputStream = connection.getInputStream();
myReader = new BufferedReader(new InputStreamReader(myInputStream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = myReader.readLine()) != null) {
buffer.append(line);
}
String Json_data = buffer.toString();
videoLiast1 = new ArrayList<>();
JSONObject parentObj = new JSONObject(Json_data);
JSONArray dataArray = parentObj.getJSONArray("data");
JSONObject tabObject = dataArray.getJSONObject(tab_id);
JSONArray videoArray = tabObject.getJSONArray("videos");
for (int i = 0; i < videoArray.length(); i++) {
int len=dataArray.length();
SetDatails setDatails = new SetDatails();
JSONObject arrayChild = videoArray.getJSONObject(i);
String vid_ID = arrayChild.getString("id");
setDatails.setVidID(vid_ID);
String movie_title = arrayChild.getString("name");
setDatails.setTitle(movie_title);
String movie_catagory = arrayChild.getString("category_name");
setDatails.setGenre(movie_catagory);
videoLiast1.add(setDatails);
}
return videoLiast1;
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (myReader != null) {
myReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected void onPostExecute(List<SetDatails> videoList) {
super.onPostExecute(videoList);
if(videoList!=null) {
try {
MyListAdapter myListAdapter = new MyListAdapter(context1, videoList);
listView1.setAdapter(myListAdapter);
}catch (Exception ex)
{
ex.printStackTrace();
}
}
}
}
I have created an Array adapter to fill list view.
public class MyListAdapter extends ArrayAdapter<SetDatails>{
public static int count =5;
List<SetDatails> videoList;
MyListAdapter(Context context,List<SetDatails> object){
super(context,R.layout.tab2_bookchilds,object);
videoList = object;
}
/**
* {#inheritDoc}
*/
#Override
public int getCount() {
return super.getCount();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater=LayoutInflater.from(getContext());
View view = layoutInflater.inflate(R.layout.tab2_bookchilds, parent, false);
TextView title = (TextView)view.findViewById(R.id.txt_title);
title.setText(videoList.get(position).getTitle());
ImageView imgV_Thumbnail = (ImageView) view.findViewById(R.id.imgV_thumbnail);
Picasso.with(getContext())
.load(videoList.get(position).getThumbnail())
.error(R.drawable.icon_white)
.into(imgV_Thumbnail);
return view;
}
}
I have searched a lot and many people suggest getCount() method although I tried a lot to use this method but don't know how to do that.
Please guys help me because my app is ready to upload but I can't solve this one issue.
I am trying to fetch data using AsyncTask & displaying into a ListView. It never calls getView(), I checked getCount() return always 0.
MainActivityFragment.java
public class MainActivityFragment extends Fragment {
private final String LOG_TAG = MainActivityFragment.class.getSimpleName();
SourceAdapter adapter;
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
adapter = new SourceAdapter(getActivity());
ListView listView = (ListView) rootView.findViewById(R.id.listView);
listView.setAdapter(adapter);
Log.d(LOG_TAG,"after list view set to adapter");
return rootView;
}
#Override
public void onStart() {
new FetchDataTask().execute();
super.onStart();
}
public class FetchDataTask extends AsyncTask<String, Void, SourceObject[]>{
private final String LOG_TAG = FetchDataTask.class.getSimpleName();
private SourceObject[] getSourceDataFromJson(String jsonStr)throws JSONException{
JSONArray jsonArray = new JSONArray(jsonStr);
SourceObject[] sourceObjects = new SourceObject[jsonArray.length()];
for (int i=0; i<jsonArray.length();i++){
sourceObjects[i] = new SourceObject(
jsonArray.getJSONObject(i).getJSONObject("commit").getJSONObject("author").getString("name"),
jsonArray.getJSONObject(i).getJSONObject("commit").getJSONObject("author").getString("name"),
jsonArray.getJSONObject(i).getJSONObject("commit").getString("message")
);
}
return sourceObjects;
}
#Override
protected SourceObject[] doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String jsonStr = null;
try {
String baseUrl = "https://api.github.com/repos/rails/rails/commits";
URL url = new URL(baseUrl);
Log.d(LOG_TAG,"URL IS "+url);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null)
return null;
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null){
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
jsonStr = buffer.toString();
Log.d(LOG_TAG,"JSON STRING "+jsonStr);
}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 {
return getSourceDataFromJson(jsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(SourceObject[] strings) {
adapter.notifyDataSetChanged();
super.onPostExecute(strings);
}
}
}
SourceAdapter.java
public class SourceAdapter extends BaseAdapter {
private final String LOG_TAG = SourceAdapter.class.getSimpleName();
Context context;
ArrayList<SourceObject> objects = new ArrayList<SourceObject>();
public SourceAdapter(Context context) {
this.context = context;
}
#Override
public int getCount() {
Log.d(LOG_TAG,"getCount called "+objects.size());
return objects.size();
}
#Override
public Object getItem(int position) {
Log.d(LOG_TAG,"getItem called");
return objects.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(LOG_TAG,"get view method is called");
SourceObject sourceObject = (SourceObject) getItem(position);
if (convertView == null){
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item_source,parent,false);
}
TextView personName = (TextView) convertView.findViewById(R.id.person_name);
TextView commit = (TextView) convertView.findViewById(R.id.xxx);
TextView commitMessage = (TextView) convertView.findViewById(R.id.commit_message);
personName.setText(sourceObject.getPersonName());
commit.setText(sourceObject.getCommit());
commitMessage.setText(sourceObject.getCommitMessage());
return convertView;
}
}
Please help.
You are not setting data retrieved from AsyncTask to adapter.
Add this method to your adapter class:
public void setItems(SourceObject[] items) {
this.objects = new ArrayList<SourceObject>();
for(SourceObject item : items){
this.objects.add(item);
}
this.notifyDataSetChanged();
}
And change onPostExecute of AsyncTask to:
#Override
protected void onPostExecute(SourceObject[] strings) {
adapter.setItems(strings);
super.onPostExecute(strings);
}
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.
The problem is that, I don't get any error, except that the data doesn't get loaded in the textViews of the customized ListView, all I get is a blank output. I didn't have problems before I started using Loaders.
MSKFragment.java (The Fragment class)
public class MSKFragment extends android.support.v4.app.Fragment implements LoaderManager.LoaderCallbacks<Cursor>
{
private ServiceAdapter mServiceAdapter;
public static final int SERVICE_LOADER = 0;
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle args)
{
Uri serviceUri = ServiceContract.ServiceEntry.buildServiceUri(i);
return new CursorLoader(getActivity(), serviceUri, null, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
mServiceAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
mServiceAdapter.swapCursor(null);
}
public MSKFragment()
{
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.menu_fragment_msk, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == R.id.action_refresh)
{
//Moving functions to a helper class, so that when Activity starts the data can be displayed
updateServices();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
mServiceAdapter = new ServiceAdapter(getActivity(), null, 0);
View rootView = inflater.inflate(R.layout.fragment_msk, container, false);
ListView listView = (ListView) rootView.findViewById(R.id.listViewMainService);
listView.setAdapter(mServiceAdapter);
return rootView;
}
#Override
public void onStart()
{
super.onStart();
//Refresh called and service updated when activity starts
updateServices();
}
private void updateServices()
{
FetchServicesTask serviceTask = new FetchServicesTask(getActivity());
serviceTask.execute();
}
}
ServiceAdapter.java (Custom Adapter class)
public class ServiceAdapter extends CursorAdapter
{
public ServiceAdapter(Context context, Cursor c, int flags)
{
super(context, c, flags);
}
private String convertCursorRowToUXFormat(Cursor cursor) {
// get row indices for our cursor
int idx_name = cursor.getColumnIndex(ServiceContract.ServiceEntry.COLUMN_NAME);
int idx_organizationName = cursor.getColumnIndex(ServiceContract.ServiceEntry.COLUMN_ORGANIZATION_NAME);
int idx_price = cursor.getColumnIndex(ServiceContract.ServiceEntry.COLUMN_PRICE);
return cursor.getString(idx_name) + "-" + cursor.getString(idx_organizationName) +
" - " + cursor.getString(idx_price);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
View view = LayoutInflater.from(context).inflate(R.layout.list_item_main, parent, false);
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor)
{
TextView tv = (TextView)view;
tv.setText(convertCursorRowToUXFormat(cursor));
}
}
FetchServicesTask.java (Performing the Async Task)
public class FetchServicesTask extends AsyncTask<String, Void, Void>
{
private final String LOG_TAG = FetchServicesTask.class.getSimpleName();
private final Context mContext;
private boolean DEBUG = true;
public FetchServicesTask(Context context )
{
mContext = context;
}
private String[] getServicesDatafromJson(String serviceJsonStr) throws JSONException
{
final String MSK_NAME = "name";
final String MSK_PRICE = "price";
final String MSK_ORG_NAME = "organizationName";
final String MSK_POSTED_USER = "postedUser";
final String MSK_PROFILE = "profile";
int totalResults = 25;
String resultStrs[] = new String[totalResults];
try
{
JSONArray serviceArray = new JSONArray(serviceJsonStr);
Vector<ContentValues> cVVector = new Vector<ContentValues>(serviceArray.length());
for(int i=0;i<serviceArray.length();i++)
{
String name, organizationName, price;
JSONObject serviceObject = serviceArray.getJSONObject(i);
name = serviceObject.getString(MSK_NAME);
price = serviceObject.getString(MSK_PRICE);
JSONObject postedUserObject = serviceObject.getJSONObject(MSK_POSTED_USER);
JSONObject profileObject = postedUserObject.getJSONObject(MSK_PROFILE);
organizationName = profileObject.getString(MSK_ORG_NAME);
ContentValues serviceValues = new ContentValues();
serviceValues.put(ServiceContract.ServiceEntry.COLUMN_NAME, name);
serviceValues.put(ServiceContract.ServiceEntry.COLUMN_ORGANIZATION_NAME, organizationName);
serviceValues.put(ServiceContract.ServiceEntry.COLUMN_PRICE, price);
cVVector.add(serviceValues);
}
int inserted = 0;
if(cVVector.size()>0)
{
ContentValues[] cvArray = new ContentValues[cVVector.size()];
cVVector.toArray(cvArray);
inserted = mContext.getContentResolver().bulkInsert(ServiceContract.ServiceEntry.CONTENT_URI, cvArray);
}
Log.d(LOG_TAG, "FetchServicesTask Complete. " + inserted + " Inserted");
}
catch(JSONException e)
{
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
/////////////////////////////// NETWORKING BOILER PLATE ///////////////////////////
#Override
protected Void doInBackground(String... params)
{
if (params.length == 0)
{
return null;
}
HttpURLConnection urlConnection = null; //Streaming data using HTTP
String serviceJsonStr = null; //raw JSON response
BufferedReader reader = null; //read text from character i/p stream
int pageNo = 1;
int numResults = 5;
try
{
//-------------------------CONNECTION--------------------//
final String SERVICE_BASE_URL = "http://myservicekart.com/public/";
final String SEARCH_BASE_URL = "http://myservicekart.com/public/search?";
final String SEARCH_PARAM = "search";
final String PAGE_PARAM = "pageno";
/*Using a helper class UriBuilder for building and manipulating URI references*/
Uri builtServiceUri = Uri.parse(SERVICE_BASE_URL);
Uri builtSearchUri = Uri.parse(SEARCH_BASE_URL).buildUpon().
appendQueryParameter(SEARCH_PARAM, "").
appendQueryParameter(PAGE_PARAM, Integer.toString(pageNo)).
build();
URL searchUrl = new URL(builtSearchUri.toString());
Log.v(LOG_TAG, "Built SearchUri" +builtSearchUri.toString());
urlConnection = (HttpURLConnection) searchUrl.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//------------------------BUFFERING---------------------//
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if(inputStream==null)
{
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while((line = reader.readLine()) != null)
{
buffer.append(line + "\n");
}
if(buffer.length()==0)
{
return null;
}
serviceJsonStr = buffer.toString();
getServicesDatafromJson(serviceJsonStr);
Log.v(LOG_TAG, "Services JSON String: " +serviceJsonStr);
}
catch(IOException e)
{
Log.e(LOG_TAG, "Error cannot connect to URL", e);
return null;
}
catch (JSONException e)
{
e.printStackTrace();
}
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;
}
}
In onCreate, you need to init your loader:
getLoaderManager().initLoader(SERVICE_LOADER , null, this);
// Or if you are using the support library, use this:
// getSupportLoaderManager().initLoader(SERVICE_LOADER , null, this);