My JSON file that I host in my VPS is 2.2 MB and when I use OkHttp to create a request to retrieve it and then log the JSON I see that not all the JSON was requested.
My code:
public void sendJSONRequest() {
// init http client
mOkHttpClient = new OkHttpClient();
// init a request
mRequest = new okhttp3.Request.Builder().url(url).build();
// execute the request (async)
mOkHttpClient.newCall(mRequest).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, e.getMessage());
}
#Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
Log.i(TAG, response.body().string());
parseGameJSONResponse(response.body().string());
}
});
}
The error that gets throw within parseGameJSONResponse:
java.lang.IllegalStateException: closed
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398)
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392)
at okhttp3.internal.Util.bomAwareCharset(Util.java:449)
at okhttp3.ResponseBody.string(ResponseBody.java:174)
The error is thrown because the JSON was cut
parse json method:
public ArrayList<Game> parseGameJSONResponse(String json) {
ArrayList<Game> upcomingGames = new ArrayList<>();
// Main JSON Object
JSONObject mainJsonObject = null;
try {
mainJsonObject = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
}
boolean removeDuplicates = mSettingsValue.getRemoveDuplicates();
if (mainJsonObject != null) {
// MAIN JSON Data Array
JSONArray jsonArray = null;
try {
jsonArray = mainJsonObject.getJSONArray("data");
} catch (JSONException e) {
e.printStackTrace();
}
if (jsonArray != null && jsonArray.length() > 0) {
try {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject gameObject = jsonArray.getJSONObject(i);
Game game = new Game();
if (gameObject.has("id")) {
game.id = gameObject.getInt("id");
}
if (gameObject.has("name")) {
String name = gameObject.getString("name");
game.name = name;
if (name.endsWith("Edition") && removeDuplicates) {
// skip this iteration because it's a special edition and we don't want editions if setting is set to true
continue;
}
}
if (gameObject.has("slug")) {
// Creates the URL here
game.url = gameObject.getString("slug");
}
if (gameObject.has("updated_at")) {
game.updated_at = gameObject.getLong("updated_at");
}
if (gameObject.has("summary")) {
game.summary = gameObject.getString("summary");
}
if (gameObject.has("first_release_date")) {
game.first_release_date = gameObject.getLong("first_release_date");
}
// Game Release Dates
if (gameObject.has("release_dates")) {
JSONArray jsonReleaseDatesArray = gameObject.getJSONArray("release_dates");
ArrayList<ReleaseDate> releaseDates = new ArrayList<>();
for (int y = 0; y < jsonReleaseDatesArray.length(); y++) {
ReleaseDate releaseDate = new ReleaseDate();
JSONObject jsonReleaseDateObject = jsonReleaseDatesArray.getJSONObject(y);
if (jsonReleaseDateObject.has("category") && !jsonReleaseDateObject.isNull("category")) {
releaseDate.category = jsonReleaseDateObject.getInt("category");
}
if (jsonReleaseDateObject.has("platform") && !jsonReleaseDateObject.isNull("platform")) {
releaseDate.platform = jsonReleaseDateObject.getInt("platform");
}
if (jsonReleaseDateObject.has("date") && !jsonReleaseDateObject.isNull("date")) {
releaseDate.date = jsonReleaseDateObject.getLong("date");
}
if (jsonReleaseDateObject.has("region") && !jsonReleaseDateObject.isNull("region")) {
releaseDate.region = jsonReleaseDateObject.getInt("region");
// Toast.makeText(getContext(), releaseDate.region + ": Region", Toast.LENGTH_SHORT).show();
}
if (jsonReleaseDateObject.has("y") && !jsonReleaseDateObject.isNull("y")) {
releaseDate.year = jsonReleaseDateObject.getInt("y");
}
if (jsonReleaseDateObject.has("m") && !jsonReleaseDateObject.isNull("m")) {
releaseDate.month = jsonReleaseDateObject.getInt("m");
}
if (jsonReleaseDateObject.has("human") && !jsonReleaseDateObject.isNull("human")) {
releaseDate.human = jsonReleaseDateObject.getString("human");
}
releaseDates.add(releaseDate);
}
game.releaseDates = releaseDates;
}
// Screenshots
if (gameObject.has("screenshots")) {
JSONArray jsonScreenshotsArray = gameObject.getJSONArray("screenshots");
ArrayList<String> screenshots = new ArrayList<>();
for (int y = 0; y < jsonScreenshotsArray.length(); y++) {
JSONObject jsonScreenshotObject = jsonScreenshotsArray.getJSONObject(y);
screenshots.add(jsonScreenshotObject.getString("cloudinary_id"));
}
game.screenshots = screenshots;
}
// Videos
if (gameObject.has("videos")) {
ArrayList<String> videos = new ArrayList<>();
JSONArray jsonVideosArray = gameObject.getJSONArray("videos");
for (int y = 0; y < jsonVideosArray.length(); y++) {
JSONObject jsonVideoObject = jsonVideosArray.getJSONObject(y);
videos.add(jsonVideoObject.getString("video_id"));
}
game.videos = videos;
}
// Cover image
if (gameObject.has("cover")) {
JSONObject jsonCoverObject = gameObject.getJSONObject("cover");
game.cover = jsonCoverObject.getString("cloudinary_id");
}
// Websites
if (gameObject.has("websites")) {
JSONArray jsonWebsitesArray = gameObject.getJSONArray("websites");
ArrayList<Website> websites = new ArrayList<>();
for (int y = 0; y < jsonWebsitesArray.length(); y++) {
Website website = new Website();
JSONObject jsonWebsiteObject = jsonWebsitesArray.getJSONObject(y);
website.category = jsonWebsiteObject.getInt("category");
website.url = jsonWebsiteObject.getString("url");
websites.add(website);
}
game.websites = websites;
}
upcomingGames.add(game);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Toast.makeText(getContext(), "" + upcomingGames.size(), Toast.LENGTH_SHORT).show();
return upcomingGames;
}
Thank you guys. Really appreciate any kind of help so thanks
It seems it tries to read same InputStream twice (may not save in memory).
I think you should use just response.string() instead of response.body().string().
Also if you think it might be related to timing you can edit timeouts.
client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
For more look at this.
https://github.com/square/okhttp/issues/1240
Related
I am trying to implement tokenization in my Android app, and for that I always need to add the authorization header to my request anytime I make one to the server. The problem is that when I debug the server instance, even if the request is made, there is no Authorization header added in it that
Here is my code
private void syncDatabases()
{
String tag_json_obj = "json_obj_req";
String uri = "random_url";
final ProgressDialog pDialog = new ProgressDialog(this);
pDialog.setMessage("Please wait while syncing");
pDialog.show();
List<Plane> allPlane = service.gettAllPlane();
Gson gson = new Gson();
JSONArray jsArray = new JSONArray();
for (Plane p : allPlane)
{
String jsonString = gson.toJson(p);
try {
JSONObject obj = new JSONObject(jsonString);
obj.remove("ID");
jsArray.put(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
JsonArrayRequest jsonObjReq = new JsonArrayRequest(Request.Method.POST, uri, jsArray, new Response.Listener<JSONArray>()
{
#Override
public void onResponse(JSONArray response)
{
ArrayList<Plane> newList = new ArrayList<>();
try
{
for(int i=0;i<response.length();i++)
{
String planeName,planeEngine,planeProducer,planeCountry,planeYear,wikiLink,ID;
JSONObject pl = response.getJSONObject(i);
String p1 = pl.optString("ID");
if (pl != null && !p1.isEmpty())
ID = pl.getString("ID");
else
ID = "0";
String p2 = pl.optString("planeName");
if (p2 != null && !p2.isEmpty())
planeName = pl.getString("planeName");
else
planeName = "";
String p3 = pl.optString("planeEngine");
if (p3 != null && !p3.isEmpty())
planeEngine = pl.getString("planeEngine");
else
planeEngine = "";
String p4 = pl.optString("planeProducer");
if (p4 != null && !p4.isEmpty())
planeProducer = pl.getString("planeProducer");
else
planeProducer = "";
String p5 = pl.optString("planeCountry");
if (p5 != null && !p5.isEmpty())
planeCountry = pl.getString("planeCountry");
else
planeCountry = "";
String p6 = pl.optString("planeYear");
if (p6 != null && !p6.isEmpty())
planeYear = pl.getString("planeYear");
else
planeYear = "0";
String p7 = pl.optString("wikiLink");
if (p7 != null && !p7.isEmpty())
wikiLink = pl.getString("wikiLink");
else
wikiLink = "";
Plane plf = new Plane(Integer.parseInt(ID),planeName,planeEngine,planeProducer,planeCountry,Integer.parseInt(planeYear),wikiLink);
newList.add(plf);
}
}
catch (JSONException e)
{
e.printStackTrace();
}
service.deleteAllFromPlane();
for (Plane p : newList)
{
boolean ok = service.addNewPlane(p);
}
pDialog.dismiss();
tab1.onIorU();
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
Log.e("ERROR", "Error occurred ", error);
pDialog.dismiss();
}
})
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
SharedPreferences settings = PreferenceManager
.getDefaultSharedPreferences(MainActivity.this);
String auth_token_string = settings.getString("token", "");
Map<String, String> params = new HashMap<>();
params.put("Content-Type", "application/json; charset=UTF-8");
params.put("Authorization", auth_token_string);
return params;
}
};
I already verified if auth_token_string is null (it isn't). Here is what I see on the server side (C# Web API 2 server)
And here is how I get the header:
var authorization = request.Headers.Authorization;
In the pic you can see a part of the token I try to send in the headers field though. What am I doing wrong? Thank you.
In your authorization token you are missing Type of authorization. I am asuming that you are using Bacis auth, so try using this:
params.put("Authorization", "Basic " + auth_token_string);
I created an Android application which uses the Google Books API. When I get the JSON response from the server, I parse the response and retrieve the title, authors, category, publisher, page count, thumbnail and some more information about the book. The problem is that some books in the JSON response don't have the thumbnail key or category key. When I try to get those JSON key values the program throws an error and consequently skips the code of adding other books after the error occurred.
I solved that with nested try catch blocks. For example, if there isn't a publisher key in the response, then I would return null.
String publisher;
try {
publisher = volumeInfo.getString("publisher");
} catch (JSONException e) {
publisher = null;
}
Here is how the whole method for parsing the JSON response looks like:
private List<BookData> parseJsonResponse(String jsonResponse) {
List<BookData> bookData = new ArrayList<>();
try {
JSONObject rootObject = new JSONObject(jsonResponse);
JSONArray itemsArray = rootObject.getJSONArray("items");
for (int i = 0; i < itemsArray.length(); i++) {
JSONObject itemObject = itemsArray.getJSONObject(i);
JSONObject volumeInfo =
itemObject.getJSONObject("volumeInfo");
String title;
try {
title = volumeInfo.getString("title");
} catch (JSONException e) {
title = null;
}
ArrayList<String> authors;
try {
JSONArray authorsArray =
volumeInfo.getJSONArray("authors");
authors = new ArrayList<>();
for (int j = 0; j < authorsArray.length(); j++) {
authors.add(authorsArray.getString(j));
}
} catch (JSONException e) {
authors = null;
}
ArrayList<String> categories;
try {
JSONArray categoriesArray =
volumeInfo.getJSONArray("categories");
categories = new ArrayList<>();
for (int k = 0; k < categoriesArray.length(); k++) {
categories.add(categoriesArray.getString(k));
}
} catch (JSONException e) {
categories = null;
}
String publisher;
try {
publisher = volumeInfo.getString("publisher");
} catch (JSONException e) {
publisher = null;
}
String publishedDate;
try {
publishedDate =
volumeInfo.getString("publishedDate");
} catch (JSONException e) {
publishedDate = null;
}
int pageCount;
try {
pageCount = volumeInfo.getInt("pageCount");
} catch (JSONException e) {
pageCount = 0;
}
String language;
try {
language = volumeInfo.getString("language");
} catch (JSONException e) {
language = null;
}
String description;
try {
description = volumeInfo.getString("description");
} catch (JSONException e) {
description = null;
}
String bookWebsite;
try {
bookWebsite = volumeInfo.getString("infoLink");
} catch (JSONException e) {
bookWebsite = null;
}
Bitmap thumbnail;
try {
JSONObject imageLink =
volumeInfo.getJSONObject("imageLinks");
String thumbnailUrl =
imageLink.getString("thumbnail");
thumbnail = getThumbnailBitmap(thumbnailUrl);
} catch (JSONException e) {
thumbnail = null;
}
// Add a new BookData object to the list
bookData.add(new BookData(title, thumbnail, authors,
categories, publisher, publishedDate,
pageCount, language, description,
bookWebsite));
}
} catch (JSONException e) {
Log.e(LOG_TAG, null, e);
}
return bookData;
}
After I complete my parsing, I have to update my views. I am using a list view, so the adapter needs to handle the views inflation.
I had to add an if statement to check if the variable is not null, then for example set the text of the text view. Else I set the text to "Publisher not available".
TextView publisher = listView.findViewById(R.id.book_publisher);
if (bookData.getPublisher() != null) {
publisher.setText(bookData.getPublisher());
} else {
publisher.setText("Publisher not available");
}
Here is how the whole adapter looks like:
public class BookDataAdapter extends ArrayAdapter<BookData> {
public BookDataAdapter(#NonNull Context context, #NonNull
List<BookData> bookDatas) {
super(context, 0, bookDatas);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView,
#NonNull ViewGroup parent) {
View listView = convertView;
if (listView == null) {
listView = LayoutInflater.from(getContext())
.inflate(R.layout.book_list_item, parent, false);
}
// Get current BookData object
BookData bookData = getItem(position);
ImageView thumbnail = listView.findViewById(R.id.book_thumbnail);
if (bookData.getThumbnail() != null) {
thumbnail.setImageBitmap(bookData.getThumbnail());
} else {
// Set default thumbnail
thumbnail.setImageResource(R.drawable.default_thumbnail);
}
TextView title = listView.findViewById(R.id.book_title);
if (bookData.getTitle() != null) {
title.setText(bookData.getTitle());
} else {
title.setText("Title not available");
}
TextView author = listView.findViewById(R.id.book_author);
if (bookData.getAuthors() != null) {
author.setText(listToString(bookData.getAuthors()));
} else {
author.setText("Authors not available");
}
TextView category = listView.findViewById(R.id.book_category);
if (bookData.getCategories() != null) {
category.setText("Category: " +
listToString(bookData.getCategories()));
} else {
category.setText("Category not available ");
}
TextView publisher = listView.findViewById(R.id.book_publisher);
if (bookData.getPublisher() != null) {
publisher.setText(bookData.getPublisher() + ", ");
} else {
publisher.setText("Publisher not available, ");
}
TextView publishedDate =
listView.findViewById(R.id.book_published_date);
if (bookData.getPublishedDate() != null) {
publishedDate.setText(bookData.getPublishedDate());
} else {
publishedDate.setText("Published date not available");
}
TextView pageCount = listView.findViewById(R.id.book_page_count);
if (bookData.getPageCount() != 0) {
pageCount.setText("Pages: " + bookData.getPageCount());
} else {
pageCount.setText("Page count not available");
}
TextView language = listView.findViewById(R.id.book_language);
if (bookData.getLanguage() != null) {
language.setText(bookData.getLanguage());
} else {
language.setText("Language not available");
}
TextView description =
listView.findViewById(R.id.book_description);
if (bookData.getDescription() != null) {
description.setText(bookData.getDescription());
} else {
description.setText("Description not available");
}
return listView;
}
private String listToString(List<String> list) {
if (list == null || list.size() == 0) {
return null;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
builder.append(list.get(i));
if (i == (list.size() - 1)) {
break;
}
builder.append(", ");
}
return builder.toString();
}
}
And lastly I want to ask a question. Is there a better way or more efficient way of parsing the JSON response with different keys, because some people say that nested try catch statements are not a good practice?
Thank you very much!!
You have two options:
Using .has():
String publisher = null;
if(volumeInfo.has("publisher")){
publisher = volumeInfo.getString("publisher");
}
Using opt instead of get (better, IMO):
String publisher = volumeInfo.optString("publisher");
opt### methods default to null for objects and 0/false for primitives, so you don't have to write try/catch blocks or if conditions. You can also specify a second parameter as default value:
String publisher = volumeInfo.optString("publisher", "no publisher");
// if publisher is not a valid key, "no publisher" will be returned
Use can you .has() property of JSONObject
if(volumeInfo.has("publisher")){
volumeInfo.getString("publisher");
}
You don't need to wrap json operations in individual try/catch blocks.
There is a method in the json library to handle this problem:
jsonObject.isNull(key);
When you attempt to grab a value by key write it like this:
if (!volumeInfo.isNull("categories")) {
JSONArray categoryArray = volumeInfo.getJSONArray("categories");
}
In class HttpHeaderParser:
public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
long now = System.currentTimeMillis();
Map<String, String> headers = response.headers;
long serverDate = 0;
long serverExpires = 0;
long softExpire = 0;
long maxAge = 0;
boolean hasCacheControl = false;
String serverEtag = null;
String headerValue;
headerValue = headers.get("Date");
if (headerValue != null) {
serverDate = parseDateAsEpoch(headerValue);
}
headerValue = headers.get("Cache-Control");
if (headerValue != null) {
hasCacheControl = true;
String[] tokens = headerValue.split(",");
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i].trim();
if (token.equals("no-cache") || token.equals("no-store")) {
return null;
} else if (token.startsWith("max-age=")) {
try {
maxAge = Long.parseLong(token.substring(8));
} catch (Exception e) {
}
} else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {
maxAge = 0;
}
}
}
headerValue = headers.get("Expires");
if (headerValue != null) {
serverExpires = parseDateAsEpoch(headerValue);
}
serverEtag = headers.get("ETag");
// Cache-Control takes precedence over an Expires header, even if both exist and Expires
// is more restrictive.
if (hasCacheControl) {
softExpire = now + maxAge * 1000;
} else if (serverDate > 0 && serverExpires >= serverDate) {
// Default semantic for Expire header in HTTP specification is softExpire.
softExpire = now + (serverExpires - serverDate);
}
Cache.Entry entry = new Cache.Entry();
entry.data = response.data;
entry.etag = serverEtag;
entry.softTtl = softExpire;
entry.ttl = entry.softTtl;
entry.serverDate = serverDate;
entry.responseHeaders = headers;
return entry;
}
entry.softTtl = softExpire;
entry.ttl = entry.softTtl;
This two variables has the same value, so why?
In class CacheDispatcher
#Override
public void run() {
...
...
// If it is completely expired, just send it to the network.
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
...
if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request, response);
} else {
...
// Post the intermediate response back to the user and have
// the delivery then forward the request along to the network.
mDelivery.postResponse(request, response, new Runnable() {
#Override
public void run() {
try {
mNetworkQueue.put(request);
} catch (InterruptedException e) {
// Not much we can do about this.
}
}
});
}
...
}
How can I differentiate between the cast of entry.isExpired() and entry.refreshNeeded() as the values are the same?
Have a look at this post : Group Google : Volley Users - soft and hard ttl on cache
refreshNeeded() and isExpired() are not exactly the same. One compares to the ttl value and the other to softTtl. This can be used to implement request semantics where you will return a response from cache even if it is "soft" expired, but will then go to the network and refresh, returning a new response if the data has changed.
Anyone knows what might be the reason why my "invoice" does not have an value? Tallied with the php response , it is called invoice. At this line String invoice = jtransaction.getString("invoice");
public static ArrayList<Transaction> getMemberTransactions(String memberId)
{
String url= second_URL + "get_member_transactions.php";
String method = GET;
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("member_id", memberId));
JSONObject result = makeHttpRequest(url, method, params);
try {
if (result.getInt("success") == 1) {
ArrayList<Transaction> list = new ArrayList<Transaction>();
JSONArray jItems = result.getJSONArray("transaction_info");
int count = jItems.length();
for (int i = 0; i < count; i++) {
JSONObject jtransaction = jItems.getJSONObject(i);
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT,
Locale.US);
Date date = null;
try {
date = sdf.parse(jtransaction.getString("date"));
} catch (ParseException e) {
e.printStackTrace();
}
String invoice = jtransaction.getString("invoice");
String warehouse = jtransaction.getString("warehouse");
Transaction transaction = new Transaction(date,invoice, warehouse);
list.add(transaction);
}
return list;
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
php
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))
{
$transactionInfo[]["date"] = get_date($row['Transaction_Date']);
$transactionInfo[]["invoice"] = $row['Invoice_No'];
$transactionInfo[]["warehouse"] = $row['WarehouseName'];
}
if(!empty($transactionInfo)===true)
{
response_success($transactionInfo);
}
function response_success($transactionInfo) {
$response = array();
$response["success"] = 1;
$response["transaction_info"] = $transactionInfo;
echo json_encode($response);
exit;
}
This:
$transactionInfo[]["date"] = get_date($row['Transaction_Date']);
$transactionInfo[]["invoice"] = $row['Invoice_No'];
$transactionInfo[]["warehouse"] = $row['WarehouseName'];
will create three separate items in $transactionInfo, one containing date, one with invoice and one with warehouse.
Example:
array(3) {
[0]=>
array(1) {
["date"]=>
string(10) "2014-10-20"
}
[1]=>
array(1) {
["invoice"]=>
string(5) "08/15"
}
[2]=>
array(1) {
["warehouse"]=>
int(13)
}
}
I suppose you want them in one item, so you have to build it like this:
$item["date"] = get_date($row['Transaction_Date']);
$item["invoice"] = $row['Invoice_No'];
$item["warehouse"] = $row['WarehouseName'];
// now add the item to the array
$transactionInfo[] = $item;
Example:
array(1) {
[0]=>
array(3) {
["date"]=>
string(10) "2014-10-20"
["invoice"]=>
string(5) "08/15"
["warehouse"]=>
int(13)
}
}
I have a listview that is populated thru SQLite with cache data. After it finishes loading. in the background I check for new data and get a returned JSON result from a MySQL db.
In my onPostExecute of this background task, when this code is ran (the code below), and while it is being looped thru (a maximum of 50 loops), the UI thread is blocked and scrolling a ListView is not possible. Here is code:
if (result.length() != 0) {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int ii = 0; ii < jArray.length(); ii++) {
json_data = jArray.getJSONObject(ii);
item = json_data.getString("item");
cat = json_data.getString("category");
user = json_data.getString("username");
userId = json_data.getLong("user_id");
review = json_data.getString("review");
reviewId = json_data.getLong("review_id");
itemId = json_data.getLong("item_id");
commentCount = json_data.getLong("commentCount");
url = json_data.getString("name");
url = pathUrl + url; // for profile icon
date = json_data.getString("date");
rating = json_data.getDouble("rating");
upVote = json_data.getLong("good");
wiki = json_data.getString("wiki");
watchItems.add(item);
watchCats.add(cat);
watchUsers.add(user);
watchReviews.add(review);
watchUrl.add(url);
watchDateList.add(date);
watchWikiList.add(wiki);
watchItemIdList.add(String.valueOf(itemId));
watchUserIds.add(String.valueOf(userId));
watchReviewId.add(String.valueOf(reviewId));
watchRating.add(String.valueOf(rating));
watchCommentCount.add(String.valueOf(commentCount));
watchUpVote.add(String.valueOf(upVote));
Rateit.haveFollowing = "1";
if (Rateit.isUserLoggedIn == true) {
boolean oldReview = datasource
.getReviewIds(reviewId);
if (!oldReview) {
// Cache Network Items
datasource.createTrendWatch(itemId, item,
review, reviewId, cat, user,
String.valueOf(userId), url, date,
commentCount, rating, upVote, 0,
wiki);
}
}
FollowingItems wti = new FollowingItems(
Long.valueOf(watchItemIdList.get(i)),
watchItems.get(i), watchCats.get(i),
watchReviews.get(i),
Long.valueOf(watchReviewId.get(i)),
watchUsers.get(i),
Long.valueOf(watchUserIds.get(i)),
watchUrl.get(i), watchDateList.get(i),
Long.valueOf(watchCommentCount.get(i)),
Double.valueOf(watchRating.get(i)),
Long.valueOf(watchUpVote.get(i)),
watchWikiList.get(i++));
watchingListObject.add(wti);
}
}
Why is this happening? And how can I prevent my code to prevent this? Are there any optimizations I can make?
Edit: Someone below requested full task code.
Below repeats the code above but in context with entire task.
public static class FollowingTask extends AsyncTask<String, String, Void> {
protected InputStream is = null;
protected String result = "";
protected String userId;
protected ArrayList<FollowingItems> watchingListObject;
protected Context mContext;
public FollowingTask(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
if (mContext != null && (fromRefresh == false)) {
((MainFragmentActivity) mContext)
.setSupportProgressBarIndeterminateVisibility(true);
}
resetLists();
if (PrefActivity.getUserLoggedInStatus(mContext) == true) {
userId = PrefActivity.getLoggedInUserId(mContext);
} else {
userId = "-1";
}
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
datasource.purgeItemWatchingTable();
Log.d("1", "Back");
String url_select = "http://www.---.info/includes_mc_php/featured_watching.php";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
param.add(new BasicNameValuePair("user_id", userId));
param.add(new BasicNameValuePair("v2", "true"));
try {
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// read content
is = httpEntity.getContent();
} catch (Exception e) {
e.printStackTrace();
}
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void v) {
String pathUrl = Rateit.PROFILE_PIC_URL;
String item, cat, user, review, url, date, following, wiki;
long itemId, reviewId, userId, commentCount, upVote;
double rating;
int i = 0;
watchingListObject = new ArrayList<FollowingItems>();
try {
String c = String.valueOf(result.charAt(0));
if (c.equals("{")) {
JSONObject jsonObject = new JSONObject(result);
following = jsonObject.getString("following");
if (following.equals("0")) {
Rateit.haveFollowing = "0";
}
} else {
if (result.length() != 0) {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int ii = 0; ii < jArray.length(); ii++) {
json_data = jArray.getJSONObject(ii);
item = json_data.getString("item");
cat = json_data.getString("category");
user = json_data.getString("username");
userId = json_data.getLong("user_id");
review = json_data.getString("review");
reviewId = json_data.getLong("review_id");
itemId = json_data.getLong("item_id");
commentCount = json_data.getLong("commentCount");
url = json_data.getString("name");
url = pathUrl + url; // for profile icon
date = json_data.getString("date");
rating = json_data.getDouble("rating");
upVote = json_data.getLong("good");
wiki = json_data.getString("wiki");
watchItems.add(item);
watchCats.add(cat);
watchUsers.add(user);
watchReviews.add(review);
watchUrl.add(url);
watchDateList.add(date);
watchWikiList.add(wiki);
watchItemIdList.add(String.valueOf(itemId));
watchUserIds.add(String.valueOf(userId));
watchReviewId.add(String.valueOf(reviewId));
watchRating.add(String.valueOf(rating));
watchCommentCount.add(String.valueOf(commentCount));
watchUpVote.add(String.valueOf(upVote));
Rateit.haveFollowing = "1";
if (Rateit.isUserLoggedIn == true) {
boolean oldReview = datasource
.getReviewIds(reviewId);
if (!oldReview) {
// Cache Network Items
datasource.createTrendWatch(itemId, item,
review, reviewId, cat, user,
String.valueOf(userId), url, date,
commentCount, rating, upVote, 0,
wiki);
}
}
FollowingItems wti = new FollowingItems(
Long.valueOf(watchItemIdList.get(i)),
watchItems.get(i), watchCats.get(i),
watchReviews.get(i),
Long.valueOf(watchReviewId.get(i)),
watchUsers.get(i),
Long.valueOf(watchUserIds.get(i)),
watchUrl.get(i), watchDateList.get(i),
Long.valueOf(watchCommentCount.get(i)),
Double.valueOf(watchRating.get(i)),
Long.valueOf(watchUpVote.get(i)),
watchWikiList.get(i++));
watchingListObject.add(wti);
Log.d("1", "Post 2");
}
} else {
Rateit.haveFollowing = "2";
}
}
} catch (JSONException e1) {
e1.printStackTrace();
Rateit.haveFollowing = "2";
} catch (ParseException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.d("1", "Post COMPLETE");
mPullRefreshListView.onRefreshComplete();
// Reset Trending List on Pull-to-Refresh
if (mContext != null) {
if (watchUsers.size() == 0) {
l.setVisibility(View.VISIBLE);
tv.setTypeface(TypeFace.get(mContext, Rateit.BPREPLAY));
} else {
l.setVisibility(View.GONE);
}
if (mContext != null) {
listView.setAdapter(null);
if (watchItems.size() > 0) {
wAdapter = new FollowingAdapter(mContext,
watchingListObject, TypeFace.get(mContext,
Rateit.BPREPLAY), TypeFace.get(
mContext, Rateit.ROBOTO_LIGHT),
TypeFace.get(mContext, Rateit.ROBOTO_THIN),
TypeFace.get(mContext, Rateit.ROBOTO_REGULAR));
listView.setAdapter(wAdapter);
}
}
}
if (mContext != null && (fromRefresh == false)) {
((MainFragmentActivity) mContext)
.setSupportProgressBarIndeterminateVisibility(false);
MainFragmentActivity.dismissDialog(mContext);
}
fromRefresh = false;
}
}
onPostExecute runs on the UI thread. It will block the UI. doInBackground runs in the background. You should perform heavy opertaions in the doInBackground (not in onPostExecute)
Solution: you should move the parsing etc. from the onPostExecute to doInBackground and use the onPostExecute just for binding the processed information to the UI.
I would suggest as first thing to profile that code and measure how much time exactly is spent to execute it. This way at least you understand if your problem is really here or somewhere else