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);
}
});
Related
I am trying to get strings(usernames) from Server wanna put it into Recycle.For that, I am using JSON to fetch data and Asynctask to generate a new thread.I successfully getting usernames from the server but failed to put them in recycleview.
This is my Mainactivity.java
public class MainActivity extends AppCompatActivity {
BufferedReader reader;
private String content;
RecyclerView recyclerView;
Adapter madapter;
List<String> data = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new ApiAsyncTask().execute();
}
private class ApiAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
getData();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
recyclerView=(RecyclerView)findViewById(R.id.rv123);
recyclerView.setLayoutManager(new LinearLayoutManager());
data.add("name");
Dataadapter madapter = new Dataadapter(data);
recyclerView.setAdapter(madapter);
}
}
private void getData(){
try {
URL url = new URL("https://jsonplaceholder.typicode.com/comments");
URLConnection conn = url.openConnection();
conn.setDoOutput(false);
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
// Append server response in string
sb.append(line + " ");
}
// Append Server Response To Content String
content = sb.toString();
Log.e("TAG", "Response is -> " + content);
JSONArray jsonArray = new JSONArray(content);
for(int i=0;i<=4;i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
String name = jsonObject.getString("name");
Log.e("TAG", "Username is -> " + name);}
}
catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
This is my Adapter
public class Dataadapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public TextView textView;
private List<String> data;
public Dataadapter(List<String> data) {
this.data = data;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv);
}}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View dataView = layoutInflater.inflate(R.layout.container, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(dataView);
return myViewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
textView.setText(data.get(position));
}
#Override
public int getItemCount() {
return data.size();
}
}
Using 2 XML files.One is Mainactivity.xml and other is Container.xml.Please help me on how to show usernames (which I fetched from the server)into recycleview.For now, when I run the app, it just showing the layout only.Not getting any username in that layout.But in my log, I can see the usernames.Thank u
Just add the objects to your list
for(int i=0;i<=4;i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
data.add(jsonObject.getString("name"));
}
And the LinearLayoutManager constructor takes one parameter, a Context.
In your onPostExecute, do this -
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
Try this code, I tested it and it's working.
Here's MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
BufferedReader reader;
RecyclerView recyclerView;
Dataadapter madapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.rv123);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
madapter = new Dataadapter();
recyclerView.setAdapter(madapter);
new ApiAsyncTask().execute();
}
private class ApiAsyncTask extends AsyncTask<Void, Void, List<String>> {
#Override
protected List<String> doInBackground(Void... voids) {
return getData();
}
#Override
protected void onPostExecute(List<String> names) {
madapter.updateData(names);
}
}
private List<String> getData() {
List<String> data = new ArrayList<>();
try {
URL url = new URL("https://jsonplaceholder.typicode.com/comments");
URLConnection conn = url.openConnection();
conn.setDoOutput(false);
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
// Append server response in string
sb.append(line);
}
// Append Server Response To Content String
String content = sb.toString();
Log.e("TAG", "Response is -> " + content);
JSONArray jsonArray = new JSONArray(content);
for (int i = 0; i < 50; i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String name = jsonObject.getString("name");
Log.e("TAG", "Username is -> " + name);
data.add(name);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
Log.d(TAG, "getData: " + data.size());
return data;
}
}
and here's Dataadapter.java
public class Dataadapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public TextView textView;
private List<String> data;
public Dataadapter() {
data = new ArrayList<>();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public MyViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View dataView = layoutInflater.inflate(R.layout.container, parent, false);
return new MyViewHolder(dataView);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
textView.setText(data.get(position));
}
#Override
public int getItemCount() {
return data.size();
}
public void updateData(List<String> data) {
this.data = data;
notifyDataSetChanged();
}
}
The data returned from the API endpoint contains 500 items, I used 50 instead to load faster.
You should not make holder's textView as adapter's local variable and assign value on holder's constructor. Since ViewHolder may be reused and parsed to Adapter.onBindViewHolder() and then the textView used in onBindViewHolder() method is not the textView in holder( the ViewHolder constructor not called). You can make textView as MyViewHolder's variable and use holder.getTextView().setText(item) to set text.
I am trying to get JSON data to app, but getting JSON Exception
MainActivity
public class MainActivity extends AppCompatActivity {
private ListView mListView;
private List<Project> projects = new ArrayList<>();
private ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listView);
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading....");
progressDialog.setCancelable(false);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
});
Button mFilterButton = (Button) findViewById(R.id.filter_button);
mFilterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu popupMenu = new PopupMenu(MainActivity.this,v);
popupMenu.inflate(R.menu.filter_menu);
popupMenu.show();
}
});
Button mSortButton = (Button) findViewById(R.id.sort_button);
mSortButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu popupMenu = new PopupMenu(MainActivity.this,v);
popupMenu.inflate(R.menu.sort_menu);
popupMenu.show();
}
});
new GSONExecution().execute();
}
private class GSONExecution extends AsyncTask<Void, Void, Boolean>{
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
String urlString = "http://starlord.hackerearth.com/kickstarter";
try {
URL url = new URL(urlString);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setRequestMethod("GET");
int res = httpURLConnection.getResponseCode();
if (res == 200){
InputStream inputStream = httpURLConnection.getInputStream();
String s = convertStreamToString(inputStream);
Log.v("Response :" , " is "+ s);
JSONObject rootObject = new JSONObject(s);
JSONArray jsonArray = rootObject.getJSONArray("");
for (int i=0; i<=jsonArray.length(); i++){
JSONObject contactObject = jsonArray.getJSONObject(i);
String titleValue = contactObject.getString("title");
Integer pledgedValue = contactObject.getInt("amt.pledged");
Integer backersValue = contactObject.getInt("num.backers");
Project project = new Project();
project.setPleadges(pledgedValue);
project.setBackers(backersValue);
project.settitle(titleValue);
projects.add(project);
Log.v("Object details : " , " : " + pledgedValue + " : " + backersValue);
}
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return true;
}
#Override
protected void onPostExecute(Boolean isOperationCompleted) {
super.onPostExecute(isOperationCompleted);
if (isOperationCompleted){
if (progressDialog.isShowing()){
progressDialog.dismiss();
}
ProjectAdapter adapter = new ProjectAdapter(MainActivity.this, projects);
mListView.setAdapter(adapter);
}
}
#NonNull
private String convertStreamToString(InputStream inputStream) {
StringBuilder stringBuilder = new StringBuilder();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"iso-8859-1"),8);
String line;
while ((line = bufferedReader.readLine()) != null)
stringBuilder.append(line).append("\n");
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
}
}
Project
public class Project {
String mtitle;
Integer mPleadges;
Integer mBackers;
String mNoDays;
public String gettitle() {
return mtitle;
}
public void settitle(String mtitle) {
this.mtitle = mtitle;
}
public Integer getPleadges() {
return mPleadges;
}
public void setPleadges(Integer mPleadges) {
this.mPleadges = mPleadges;
}
public Integer getBackers() {
return mBackers;
}
public void setBackers(Integer mBackers) {
this.mBackers = mBackers;
}
public String getNoDays() {
return mNoDays;
}
public void setNoDays(String mNoDays) {
this.mNoDays = mNoDays;
}
}
ProjectAdapter
class ProjectAdapter extends BaseAdapter{
private List<Project> mList;
private Context mContext;
public ProjectAdapter(MainActivity mainActivity, List<Project> projects) {
this.mList = projects;
this.mContext = mainActivity;
}
#Override
public int getCount() {
return mList.size();
}
#Override
public Object getItem(int position) {
return mList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.project_details,null,false);
final TextView projectName = (TextView) convertView.findViewById(R.id.projectName);
TextView pleadge = (TextView) convertView.findViewById(R.id.pledges);
TextView backers = (TextView) convertView.findViewById(R.id.backers);
projectName.setText(mList.get(position).gettitle());
pleadge.setText(mList.get(position).getPleadges());
backers.setText(mList.get(position).getBackers());
return convertView;
}
}
I am getting org.json.JSONException: Value
at org.json.JSON.typeMismatch(JSON.java:111)
I hope you understand problem, I am still in learning stage so please give brief answer so that i can understand.
You are getting JSONArray from Response and trying to hold on JSONObject which causes org.json.JSONException: Value at org.json.JSON.typeMismatch(JSON.java:111) error
Try this
try {
JSONArray jsonArrayLST = new JSONArray(s);
for (int i = 0; i < jsonArrayLST.length(); i++) {
JSONObject contactObject= jsonArrayLST.getJSONObject(i);
String titleValue = contactObject.getString("title");
Integer pledgedValue = contactObject.getInt("amt.pledged");
Integer backersValue = contactObject.getInt("num.backers");
Project project = new Project();
project.setPleadges(pledgedValue);
project.setBackers(backersValue);
project.settitle(titleValue);
projects.add(project);
Log.v("Object details : " , " : " + pledgedValue + " : " + backersValue);
}
} catch (JSONException e) {
e.printStackTrace();
}
Also, you need to change in your adapter while setting item to textview, because your are setting int value which causes you android.content.res.Resources$NotFoundException: String resource ID error
pleadge.setText(String.valueOf(mList.get(position).getPleadges()));
backers.setText(String.valueOf(mList.get(position).getBackers()));
[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;
}
}
}
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.