I am usind TMDb API to build a project app. Every api call gives me back 20 movies, so normally the app shows only 20 movie posters on startup. I added this code to fetch another 20 movies, using the &page= query, when the user scrolls down the grid View.
gridView.setOnScrollListener(onScrollListener());
private AbsListView.OnScrollListener onScrollListener() {
return new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
int threshold = 1;
int count = gridView.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (gridView.getLastVisiblePosition() >= count - threshold && pageCount < 2) {
Log.v(LOG_TAG, "loading more data");
// Execute LoadMoreDataTask AsyncTask
updateMovies(sortBy, true);
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
}
};
}
But this solution works really bad. If i scroll down it executes updateMovies(sortBy, true); for 2-3 times at once, jumping pages and making it impossible to read.
Also, the data shown on screen is completely replaced after every page refresh, for example if I am seeing the data on page=1 and I scroll down then i see only the data from page 2 or 3 but the original data is gone.
here is my AsyncTask
public class FetchMoviesTask extends AsyncTask<String, Void, List<Movie>> {
private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();
private final static String API_KEY = "480a9e79c0937c9f4e4a129fd0463f96";
#Override
protected List<Movie> doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String jsonStr = null;
try {
final String BASE_URL = "http://api.themoviedb.org/3/movie";
final String API_KEY_PARAM = "api_key";
final String PAGE_PARAM = "page";
URL url;
if (params[1].equals("true")){
// if a bool is true
// then I intend to load an additional page
// (needed otherwise going back from detailAct loads a new increasing page
currentPage += 1;
pageCount++;
}else{
currentPage = 1;
}
if (params[0].equals(POPULARITY_DESC)){
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendPath("popular")
.appendQueryParameter(API_KEY_PARAM, API_KEY) // my own API key
.appendQueryParameter(PAGE_PARAM , Integer.toString(currentPage))
.build();
url = new URL(builtUri.toString());
}else if(params[0].equals(RATING_DESC)) {
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendPath("top_rated")
.appendQueryParameter(API_KEY_PARAM, API_KEY)// my own API key
.appendQueryParameter(PAGE_PARAM , Integer.toString(currentPage))
.build();
url = new URL(builtUri.toString());
}else {
Log.v(LOG_TAG, "Something went wrong with URI building :(");
url = new URL("ERROR URL");
}
Log.v(LOG_TAG, "URL BUILT: " + 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) {
// 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) {
return null;
}
jsonStr = buffer.toString(); // finally parsed JSON string
} 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 getMoviesDataFromJson(jsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
// This will only happen if there was an error getting or parsing the forecast.
return null;
}
private List<Movie> getMoviesDataFromJson(String jsonStr) throws JSONException {
JSONObject movieJson = new JSONObject(jsonStr);
JSONArray movieArray = movieJson.getJSONArray("results");
List<Movie> results = new ArrayList<>();
for(int i = 0; i < movieArray.length(); i++) {
JSONObject movie = movieArray.getJSONObject(i);
Movie movieModel = new Movie(movie); // basically Movie has already the fields to fill (image,
// description, rating, etc) and this adds those values from the JSONObject
results.add(movieModel); // it does this one object at the time, for the lenght of the array
}
return results;
}
#Override
protected void onPostExecute(List<Movie> mv) {
if (mv != null) {
if (movieGridAdapter != null) {
movieGridAdapter.clear();
for (Movie movie : mv) {
movieGridAdapter.add(movie);
}
}
movies = new ArrayList<>();
movies.addAll(mv);
}
}
}
Related
I am making a simple news reader app. The news need to be shown in one RecyclerView, like a list of news. The problem is that there are a multiple URLs from whom i extract data and i know only how to parse one but dont know how to handle more of them. Here is my code:
public class NewsActivity extends AppCompatActivity {
public static final String LOG_TAG = NewsActivity.class.getSimpleName();
public static final String newsUrl1 = "http://tests.intellex.rs/api/v1/news/list?page=1";
public static final String newsUrl2 = "http://tests.intellex.rs/api/v1/news/list?page=2";
public static final String newsUrl3 = "http://tests.intellex.rs/api/v1/news/list?page=3";
public static final String newsUrl4 = "http://tests.intellex.rs/api/v1/news/list?page=4";
private NewsAdapter adapter;
private RecyclerView recyclerView;
private ArrayList<NewsModel> newsArray;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.a_news_recycler_view__);
newsArray = new ArrayList<>();
adapter = new NewsAdapter(this, newsArray);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView = (RecyclerView) findViewById(R.id.newsRecyclerView);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(getApplicationContext()));
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
NewsAsyncTask task = new NewsAsyncTask();
task.execute();
}
private class NewsAsyncTask extends AsyncTask<URL, Void, ArrayList<NewsModel>> {
#Override
protected ArrayList<NewsModel> doInBackground(URL... urls) {
URL url = createUrl(newsUrl1);
String jsonResponse = "";
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
e.printStackTrace();
}
return extractFeatureFromJson(jsonResponse);
}
#Override
protected void onPostExecute(ArrayList<NewsModel> news) {
if (news == null) {
return;
}
adapter.addAll(news);
}
private URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException exception) {
Log.e(LOG_TAG, "Error with creating URL", exception);
return null;
}
return url;
}
private String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000);
urlConnection.setConnectTimeout(15000);
urlConnection.connect();
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// function must handle java.io.IOException here
inputStream.close();
}
}
return jsonResponse;
}
private 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();
}
private ArrayList<NewsModel> extractFeatureFromJson(String newsJson) {
if (TextUtils.isEmpty(newsJson)) {
return null;
}
ArrayList<NewsModel> news_information = new ArrayList<>();
try {
JSONObject baseJsonResponse = new JSONObject(newsJson);
JSONArray newsArray = baseJsonResponse.getJSONArray("list");
for (int i = 0; i < newsArray.length(); i++) {
JSONObject news = newsArray.getJSONObject(i);
try {
news = newsArray.getJSONObject(i);
String newsImage = news.getString("image");
String newsTitle = news.getString("title");
String newsPublished = news.getString("published");
String newsAuthor = news.getString("author");
String newsID = news.getString("id");
NewsModel newsModel = new NewsModel(newsImage, newsTitle, newsPublished, newsAuthor, newsID);
news_information.add(newsModel);
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return news_information;
}
}
}
Any help would be appreciated. Thanks in advance.
Why don't you use "links" as array ?
In case you will use an array:
JSONObject jsonObject = new JSONObject();
JSONArray keys = jsonObject.getJSONArray("links");
int length = keys.length();
for (int i = 0; i < length; i++) {
new ReadJSON().execute(keys.getString(i));
}
Anyway, you take all the keys and go one after the other, and then query each
EDIT:
JSONObject jsonObject = new JSONObject(/*Your links json*/);
JSONObject links = jsonObject.get("links");
Iterator<String> keys = links.keys();
while (keys.hasNext()) {
new ReadJSON().execute(links.getString(keys.next()));
}
I have an option menu item that allows a user to see their current location (based on Zip Code) on Google Maps using an intent. Because Google Maps only accepts Lat/Lng, I am using the Geocoding API to return Lat/Lng in JSON format. Here is the code that executes once the user selects the menu item:
MainActivity.java
#Override public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent in = new Intent(this, SettingsActivity.class);
startActivity(in);
return true;
}
if (id == R.id.action_map) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String location = prefs.getString(getString(R.string.pref_location_key),
getString(R.string.pref_location_default));
FetchZipTask fzt = new FetchZipTask();
fzt.execute(location);
loc = fzt.locale;
Uri geoLocation = Uri.parse("geo:"+ loc);
Log.d("Debug", geoLocation.toString());
Intent in = new Intent(Intent.ACTION_VIEW);
in.setData(geoLocation);
if (in.resolveActivity(getPackageManager()) != null) {
startActivity(in);
}
}
return super.onOptionsItemSelected(item);
}
I am currently trying to use a public String field in the AsyncTask class that is updated when the onPostExecute() method parses the JSON and formats the retrieved Lat/Lng string. I then access this public field from the MainActivity class whenever the user selects the menu item, but the field is always null. What am I doing wrong, and is it the most effective way to leverage AsyncTask? I'm thinking there must be a better way to return the value.
FetchZipTask.java
public class FetchZipTask extends AsyncTask<String, Void, String> {
public String locale = null;
#Override protected void onPostExecute(String result) {
locale = result;
}
#Override protected String doInBackground(String... params) {
if (params.length == 0) {
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
//raw JSON response as a string
String locationJsonStr = null;
try {
final String BASE_LOCATION_URL =
"https://maps.googleapis.com/maps/api/geocode/json?";
final String ADDRESS_PARAM = "address";
final String APPID_PARAM = "key";
// URI.path vs URI.parse vs. URI Scheme
Uri builtUri = Uri.parse(BASE_LOCATION_URL)
.buildUpon()
.appendQueryParameter(ADDRESS_PARAM, params[0])
.appendQueryParameter(APPID_PARAM, BuildConfig.GOOGLE_GEOCODE_API_KEY)
.build();
//Log.d("Debug", builtUri.toString());
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 for debugging.
line.concat(" Hello ");
line.concat("\n");
buffer.append(line);
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
locationJsonStr = buffer.toString();
Log.v("debug", "Location string: " + locationJsonStr);
} catch (IOException e) {
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("ForecastFragment", "Error closing stream", e);
}
}
}
try {
return getLocationDataFromJson(locationJsonStr);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
private String getLocationDataFromJson(String forecastJsonStr) throws
JSONException {
// These are the names of the JSON objects that need to be extracted.
final String GEO_LIST = "results";
final String GEO_OBJ = "geometry";
final String GEO_LOC = "location";
final String GEO_LAT = "lat";
final String GEO_LNG = "lng";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray resultsArray = forecastJson.getJSONArray(GEO_LIST);
JSONObject resultsObj = resultsArray.getJSONObject(0);
JSONObject geoObj = resultsObj.getJSONObject(GEO_OBJ);
JSONObject latLng = geoObj.getJSONObject(GEO_LOC);
String lat = latLng.getString(GEO_LAT);
String lng = latLng.getString(GEO_LNG);
Log.d("location", "Lat:" + lat + "\n Lng:" + lng);
return lat + "," + lng;
}
}
AsyncTask is called async for a reason.
In the following code you execute your AsyncTask and then immediately try to access one of its fields:
FetchZipTask fzt = new FetchZipTask();
fzt.execute(location);
loc = fzt.locale;
That won't work because FetchZipTask may still be running when you're trying to access its locale variable.
onPostExecute() is called when the task is finished, so you should pass your result from there.
You could define an interface in FetchZipTask, pass an instance of it as a constructor param and call the appropriate method on that instance in onPostExecute():
public class FetchZipTask extends AsyncTask<String, Void, String> {
// declaring a listener instance
private OnFetchFinishedListener listener;
// the listener interface
public interface OnFetchFinishedListener {
void onFetchFinished(String result);
}
// getting a listener instance from the constructor
public FetchZipTask(OnFetchFinishedListener listener) {
this.listener = listener;
}
// ...
// calling a method of the listener with the result
#Override protected void onPostExecute(String result) {
listener.onFetchFinished(result);
}
}
In your Activity, pass an OnFetchFinishedListener when instantiating your AsyncTask:
new FetchZipTask(new FetchZipTask.OnFetchFinishedListener() {
#Override
public void onFetchFinished(String result) {
// do whatever you want with the result
Uri geoLocation = Uri.parse("geo:"+ result);
Log.d("Debug", geoLocation.toString());
Intent in = new Intent(Intent.ACTION_VIEW);
in.setData(geoLocation);
if (in.resolveActivity(getPackageManager()) != null) {
startActivity(in);
}
}
}).execute();
And that's it. Orientation change may still be a problem, so you could move your AsyncTask in a headless Fragment, or consider using a Service instead.
It's been a while since I have been using android. can you please tell me how to add OnScrollListener in this code ? Everytime I scroll down I want to fetch 5 more images.
This is the Asyncatask its working correct, but I need fetch 5 image everytime I scroll down(load more).
public class RecyclerOkHttpHandler extends AsyncTask<String, Void, String> {
private Context mContext;
private MyInterface mListener;
public String category;
public String basestart;
public String limitend;
public RecyclerOkHttpHandler(Context context, MyInterface mListener, String categ, String base, String limit){
mContext = context;
this.mListener = mListener;
category=categ;
basestart=base;
limitend=limit;
}
public interface MyInterface {
public void myMethod(ArrayList result);
}
private final String Fetch_URL = "http://justedhak.com/old-files/Recyclerview_data.php";
// ArrayList<Listitem> Listitem;
ArrayList<CategoryList> Listitem;
int resulta;
OkHttpClient httpClient = new OkHttpClient();
ListView list;
String myJSON;
JSONArray peoples = null;
InputStream inputStream = null;
#Override
protected String doInBackground(String... params) {
Log.d("okhttp Fetch_URL", Fetch_URL);
RequestBody formBody = new FormEncodingBuilder()
.add("category", category)
.add("base", basestart)
.add("limit", limitend)
.build();
Request request = new Request.Builder()
.url(Fetch_URL)
.post(formBody)
.build();
String result = null;
try {
Response response = httpClient.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
inputStream = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
result = sb.toString();
resulta = 1; //"Success
// return response.body().bytes();
} catch (Exception e) {
Toast.makeText(mContext, "Connection failed, check your connection",
Toast.LENGTH_LONG).show();
e.printStackTrace(); }
finally {
try{if(inputStream != null)inputStream.close();}catch(Exception squish){}
}
return result;
}
#Override
protected void onPostExecute(String result){
if( resulta ==1){
myJSON=result;
Log.e("result",result);
showList();
}
else{
Log.e("d","there is an error on postexecute in okhhttphandler.java");
}
}
protected void showList(){
try {
JSONObject jsonObj = new JSONObject(myJSON);
peoples = jsonObj.getJSONArray("result");
System.out.println("Length:"+peoples.length());
int J_length=peoples.length()-1;
//JSONObject maxj = peoples.getJSONObject(peoples.length() - 1);
// max of arrray
jsonObj= peoples.getJSONObject(J_length);
String j_id= jsonObj.getString("id");
int _id = Integer.parseInt(j_id);
System.out.println(j_id);
//max of
DatabaseHandler db = new DatabaseHandler(mContext);
String db_id="";
db_id = db.getmax();
if (db_id== null)
{
db_id="0";
}
int d_id = Integer.parseInt(db_id);
Log.e("db_id", db_id);
Log.e("j_id",j_id);
// if (_id < d_id) {
System.out.println("Getting json result ");
Listitem = new ArrayList<CategoryList>();
for (int i = 0; i < peoples.length(); i++) {
JSONObject c = peoples.getJSONObject(i);
String id = c.getString("id");
String url = c.getString("url");
Listitem.add(new CategoryList(id, url));
}
if (mListener != null)
mListener.myMethod(Listitem);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
This is the when I set the adapter
private String base = "0";
private String limit = "5";
final RecyclerOkHttpHandler handler = new RecyclerOkHttpHandler( this, new RecyclerOkHttpHandler.MyInterface() {
#Override
public void myMethod(ArrayList result) {
mAdapter_first = new MyAdapter(result,SearchActivity.this);
mAdapter_first.notifyDataSetChanged();
mRecyclerView_first.setAdapter(mAdapter_first);
}
},"girls jokes",base,limit);
try {
handler.execute().get();
} catch (Exception e) {
Log.d("SearchActivity error", "error in mRecyclerView_first");
e.printStackTrace();
}
For the first load, call your RecyclerOkHttpHandler AsyncTaskto get your first 5 items.
Now, for any further load, all you have to do is to check if the listView is scrolled to its bottom and you can refer to this link Find out if ListView is scrolled to the bottom? to know how to deal with it.
So, each time you detect that the user has scrolled the listview to the bottom, it's time to call the RecyclerOkHttpHandler AsynTask to get the 5 new images.
PS: You need to save the limit you have reached in each load, so that in the next load, you start loading from that limit.
Hope this helps :)
I am learning how to use onscrolllistner
The RecyclerOkHttpHandler class will execute a select with base 0 and limit 5 from server. what I want is to execute again the RecyclerOkHttpHandler to get the new data , for examle base 5 limit 10. but when adding the below on onscrolllistner
handler.execute().get();
i got this error :
Cannot execute task: the task has already been executed (a task can be executed only once)
ok i understand i cannot execute again the task , but how should i passe base and limit ?
this (it is working) will execute a class that will get images from server, however I need to pass base 0 and limit 5
final RecyclerOkHttpHandler handler = new RecyclerOkHttpHandler( this, new RecyclerOkHttpHandler.MyInterface() {
#Override
public void myMethod(ArrayList result) {
mAdapter_first = new MyAdapter(result,SearchActivity.this);
mAdapter_first.notifyDataSetChanged();
mRecyclerView_first.setAdapter(mAdapter_first);
}
},"girls",base,limit);
try {
handler.execute().get();
} catch (Exception e) {
Log.d("SearchActivity error", "error in mRecyclerView_first");
e.printStackTrace();
}
and this is the addOnScrollListener,
mRecyclerView_first.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = mRecyclerView_first.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
System.out.println("previousTotal:" + previousTotal);
System.out.println("totalItemCount:" + totalItemCount);
System.out.println("visibleItemCount:" + visibleItemCount);
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
System.out.println(totalItemCount);
Log.i("Yaeye!", "end called");
// base =String.valueOf(firstVisibleItem);
// limit=String.valueOf(visibleItemCount);
// Do something
try {
handler.execute().get();
} catch (Exception e) {
Log.d("SearchActivity error", "error in mRecyclerView_first");
e.printStackTrace();
}
loading = true;
}
}
});
this is the class RecyclerOkHttpHandler
public class RecyclerOkHttpHandler extends AsyncTask<String, Void, String> {
private Context mContext;
private MyInterface mListener;
public String category;
public String basestart;
public String limitend;
public RecyclerOkHttpHandler(Context context, MyInterface mListener, String categ, String base, String limit){
mContext = context;
this.mListener = mListener;
category=categ;
basestart=base;
limitend=limit;
}
public interface MyInterface {
public void myMethod(ArrayList result);
}
private final String Fetch_URL = "http://justedhak.com/old-files/Recyclerview_data.php";
// ArrayList<Listitem> Listitem;
ArrayList<CategoryList> Listitem;
int resulta;
OkHttpClient httpClient = new OkHttpClient();
ListView list;
String myJSON;
JSONArray peoples = null;
InputStream inputStream = null;
#Override
protected String doInBackground(String... params) {
Log.d("okhttp Fetch_URL", Fetch_URL);
RequestBody formBody = new FormEncodingBuilder()
.add("category", category)
.add("base", basestart)
.add("limit", limitend)
.build();
Request request = new Request.Builder()
.url(Fetch_URL)
.post(formBody)
.build();
String result = null;
try {
Response response = httpClient.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
inputStream = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
result = sb.toString();
resulta = 1; //"Success
// return response.body().bytes();
} catch (Exception e) {
Toast.makeText(mContext, "Connection failed, check your connection",
Toast.LENGTH_LONG).show();
e.printStackTrace(); }
finally {
try{if(inputStream != null)inputStream.close();}catch(Exception squish){}
}
return result;
}
#Override
protected void onPostExecute(String result){
if( resulta ==1){
myJSON=result;
Log.e("result",result);
showList();
}
else{
Log.e("d","there is an error on postexecute in okhhttphandler.java");
}
}
protected void showList(){
try {
JSONObject jsonObj = new JSONObject(myJSON);
peoples = jsonObj.getJSONArray("result");
System.out.println("Length:"+peoples.length());
int J_length=peoples.length()-1;
//JSONObject maxj = peoples.getJSONObject(peoples.length() - 1);
// max of arrray
jsonObj= peoples.getJSONObject(J_length);
String j_id= jsonObj.getString("id");
int _id = Integer.parseInt(j_id);
System.out.println(j_id);
//max of
DatabaseHandler db = new DatabaseHandler(mContext);
String db_id="";
db_id = db.getmax();
if (db_id== null)
{
db_id="0";
}
int d_id = Integer.parseInt(db_id);
Log.e("db_id", db_id);
Log.e("j_id",j_id);
// if (_id < d_id) {
System.out.println("Getting json result ");
Listitem = new ArrayList<CategoryList>();
for (int i = 0; i < peoples.length(); i++) {
JSONObject c = peoples.getJSONObject(i);
String id = c.getString("id");
String url = c.getString("url");
Listitem.add(new CategoryList(id, url));
}
if (mListener != null)
mListener.myMethod(Listitem);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
I read your problem again, and the solution might just be to create a new RecyclerOkHttpHandler each time. That's what the error message says and that's how AsyncTasks work. If you call .execute() once you cannot call it again, you have to create a new object.
Still you should override onPostExecute() else you are blocking the UI thread. Have a look at AsyncTask.
I need the code for RecyclerOkHttpHandler to say more...
I am working on my movie project which fetch movie poster from URL, and then putting them into a gridview. I use asynctask to fetch JSON and the parse the url within the json file. However, when I launch my app, the grid is all empty and doing nothing until I rotate my screen or resume my app. Once I rotate my screen or resume my app. It shows all picture. I remove my api key on my code here.
public class FetchMovieTask extends AsyncTask<Void, Void, ArrayList<String>> {
private final String LOG_TAG = FetchMovieTask.class.getSimpleName();
#Override
protected ArrayList<String> doInBackground(Void... params) {
String api_key = "";
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String movieJsonStr = null;
try {
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority("api.themoviedb.org")
.appendPath("3")
.appendPath("discover")
.appendPath("movie")
.appendQueryParameter("api_key", api_key);
String myUrl = builder.build().toString();
URL Url = new URL(myUrl);
Log.v(LOG_TAG, myUrl);
// 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.
movieJsonStr = 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.
movieJsonStr = null;
}
movieJsonStr = buffer.toString();
Log.v("KPN", 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 attempting
// to parse it.
movieJsonStr = null;
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 {
MovieURL = getPosterUrlFromJson(movieJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
}
private ArrayList<String> getPosterUrlFromJson(String forcastMovieStr)
throws JSONException {
final String OWM_PosterUrl = "poster_path";
final String OWM_releaseDate = "release_date";
final String OWM_overview = "overview";
final String OWM_vote_average = "vote_average";
final String OWM_original_title = "original_title";
final String OWM_results = "results";
JSONObject movieJson = new JSONObject(forcastMovieStr);
JSONArray movieArray = movieJson.getJSONArray(OWM_results);
ArrayList<String> resultStrs = new ArrayList<>();
String posterurl = "http://image.tmdb.org/t/p/w185/";
for (int i = 0; i < movieArray.length(); i++) {
// For now, using the format "Day, description, hi/low"
String title;
String overview;
String poster;
// Get the JSON object for movie poster
JSONObject moveposter = movieArray.getJSONObject(i);
poster = moveposter.getString(OWM_PosterUrl);
resultStrs.add(i,posterurl + poster);
}
return resultStrs;
}
protected void onPostExecute(ArrayList<String> strings) {
MovieURL.clear();
for (String s : strings) {
MovieURL.add(s);
}
}
Main:
public class MainActivity extends AppCompatActivity {
public static ArrayList<String> MovieURL = new ArrayList();
public static ImageListAdapter mImageListAdapter;
public GridView gridview;
#Override
protected void onStart() {
super.onStart();
new FetchMovieTask().execute();
mImageListAdapter = new ImageListAdapter(this,MovieURL);
gridview.setAdapter(mImageListAdapter);
gridview.invalidateViews();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridview = (GridView) findViewById(R.id.gridview);
}
private void updateMovieURL(){
new FetchMovieTask().execute();
gridview.invalidateViews();
}
ImagelistAdapter class
public class ImageListAdapter extends ArrayAdapter {
private Context context;
private LayoutInflater inflater;
private ArrayList<String> imageUrls;
public ImageListAdapter(Context context, ArrayList <String> imageUrls) {
super(context, R.layout.image_view, imageUrls);
this.context = context;
this.imageUrls = imageUrls;
inflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == convertView) {
convertView = inflater.inflate(R.layout.image_view, parent, false);
}
Picasso.with(context).load(imageUrls.get(position))
.placeholder(R.drawable.loading)
.into((ImageView) convertView);
return convertView;
}
}
THanks guys
In postExecute do this:
protected void onPostExecute(ArrayList<String> strings) {
MovieURL.clear();
for (String s : strings) {
MovieURL.add(s);
}
mImageListAdapter.notifyDataSetChanged();
}
I found my problem on the asynctask, I didnt override the onPostExecute method. After I override my onPostExecute, I initial my grid view
#Override
protected void onPostExecute(ArrayList<String> strings) {
super.onPostExecute(strings);
mImageListAdapter = new ImageListAdapter(MainActivity.this, MovieURL);
gridview.setAdapter(mImageListAdapter);
}