loading takes so much time sometimes in android asynctask - android

I am using AsyncTask to call the web service and render the data I got from web service.
this is working fine but sometimes Progress Dialog doesn't get dismissed and not able to see the reason for this in log also.
Example::
I have a web service which is getting called to get the list view data with indexing(for 1 it will return first 5 data and for 2 it will return second 5 data and so on)
once I click page 1 button it returns data and render the same and when I click the page 2 button it starts loading and doesn't dismiss. neither the data is rendered nor the progress dialog is dismissed.
now i closed the app and relaunched again and this time both the situation worked very well.
Any help would be appreciated
thanks in advance
Code for Asynctask :
public class getList extends AsyncTask<Void, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(getActivity());
pDialog.setCancelable(false);
pDialog.setMessage("Please wait...");
pDialog.setCanceledOnTouchOutside(false);
pDialog.show();
}
#Override
protected String doInBackground(Void... params) {
String text = null;
JSONObject json;
HttpClient httpclient = new DefaultHttpClient();
//Configuration.empcode.trim()
HttpGet httppost = new HttpGet(ListURL+UserCode+"/"+indexNo);
try {
HttpResponse response = httpclient.execute(httppost);
// for JSON:
if (response != null) {
InputStream is = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
// String result = EntityUtils.toString((HttpEntity)
// response);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
text = sb.toString();
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
return text;
}
#Override
protected void onPostExecute(String result)
{
pDialog.dismiss();
if(result!=null)
{
try
{
JSONObject resultObject = new JSONObject(result);
JSONArray resultArray = resultObject.getJSONArray("Table");
for(int i =0;i<resultArray.length();i++)
{
JSONObject resultObjects = resultArray.getJSONObject(i);
Code = resultObjects.getString("Code");
Title = resultObjects.getString("Title");
status= resultObjects.getString("status");
date= resultObjects.getString("date");
TitleList.add(Title);
CodeList.add(Code);
statusList.add(status);
dateList.add(date);
int count = db.getInProgressCount(CourseCode);
if(count==0)
{
db.addInProgress(new InProgressTable(Code,Title,status,date));
}
else
{
db.updateInProgress(new InProgressTable(Code,Title,status,date));
}
}
adapter = new CustomInProgressList(getActivity(),TitleList,CodeList,statusList,dateList);
//adapter.setCustomButtonListner(Catalog_Activity.this);
list.setAdapter(adapter);
scrollMyListViewToBottom(resultArray.length());
int count = db.getAllInProgressCount();
if (adapter.getCount()<1 && count<1){
list.setVisibility(View.GONE);
noRes.setVisibility(View.VISIBLE);
}else {
list.setVisibility(View.VISIBLE);
noRes.setVisibility(View.GONE);
}
if (resultArray.length()<5);
loadMore.setVisibility(View.GONE);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
else
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Alert");
builder.setMessage("Data is not available, Please try again later");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
dialog.cancel();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
}
I have used multiple Asynctask in my application.
Is that a Problem??

ok here is your problem -
pDialog as I understand is declared in activity. Lets see the situation with 2 requests.
when you started first one, and immediately start another - your pDialog is now new dialog (it points to another dialog) and first one exists without point to it, and it's not closed! this is why you have not closed dialog.
this will be caused in situation when:
1) first request started;
2) second request started before first request ended;
you must handle one dialog in all your requests or close dialog before it's reinitialisation.

Related

Change content of listview on button click(on same screen)

So In my MainActivity There are 3 rooms(coming from server).when i click on them popup is open.This popup will having shown the list of roomId(clicked on listview item).This works fine.
Now I need like this.In popup on click of next button next roomId with api to get its module is call and update the listview.
How i do this?
Problem is:-whenever going to do always it open with new popup.
As shown in picture I need to change the content of listview on toolbar's right arrow button.
My listview is in popup.so when i change content of listview this another new popup open for new list.
This is my 1st listview(where I load all images)
modules_list.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0,
android.view.View arg1, int arg2, long arg3) {
editor.putInt("response_position",arg2).commit();
editor.putString("roomid",response.getRooms()[arg2+1].getRooms_id().getRoomId()).commit();
String serverURL = "http://dashboard.droidhomes.in/api/module?room_id=" + response.getRooms()[arg2].getRooms_id().getRoomId();
// Use AsyncTask execute Method To Prevent ANR11 Problem
new GetallModules().execute(serverURL);
}
});
GetAllmodules class to get all modules and switches of Room:-
private class GetallModules extends AsyncTask<String, Void, Void> {
// Required initialization
// private final HttpClient Client = new DefaultHttpClient();
private String Content;
private String Error = null;
private ProgressDialog Dialog = new ProgressDialog(
MainActivity.this);
protected void onPreExecute() {
// NOTE: You can call UI Element here.
Dialog.setMessage("Please wait..");
Dialog.show();
}
// Call after onPreExecute method
protected Void doInBackground(String... urls) {
/************ Make Post Call To Web Server ***********/
BufferedReader reader = null;
try {
// Defined URL where to send data
URL url = new URL(urls[0]);
// Send POST data request
pref = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
editor = pref.edit();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
String auth_token = pref.getString("auth_token", "");
conn.setRequestProperty("Authorization", auth_token);
reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
// Read Server Response
while ((line = reader.readLine()) != null) {
// Append server response in string
sb.append(line + "\n");
}
// Append Server Response To Content String
Content = sb.toString();
} catch (Exception ex) {
Error = ex.getMessage();
} finally {
try {
reader.close();
} catch (Exception ex) {
}
}
/*****************************************************/
return null;
}
protected void onPostExecute(Void unused) {
// NOTE: You can call UI Element here.
// Close progress dialog
// Content=Content.replaceAll("<string>","");
// Content=Content.replaceAll("</string>", "");
Dialog.dismiss();
if (Error != null) {
Toast toast = Toast.makeText(getApplicationContext(),
"Bad request", Toast.LENGTH_LONG);
toast.show();
// uiUpdate.setText("Output : " + Error);
} else {
// Show Response Json On Screen (activity)
// uiUpdate.setText(Content);
/****************** Start Parse Response JSON Data *************/
// String OutputData = "";
// JSONObject jsonResponse;
Gson gson = new Gson();
final SearchResponse response = gson.fromJson(Content,
SearchResponse.class);
if (response.getStatus() == true) {
//response.getAuth_token()
if (response.getModule().length > 0) {
LayoutInflater li1 = LayoutInflater.from(MainActivity.this);
View promptsView = li1.inflate(R.layout.prompts_modulesdialog1, null);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogBuilder.setView(promptsView);
ListView list_modules = (ListView) promptsView.findViewById(R.id.lv_modules);
TextView tv_roomname = (TextView) promptsView.findViewById(R.id.tv_roomName);
ImageView iv_left=(ImageView)promptsView.findViewById(R.id.iv_left);
ImageView iv_right=(ImageView)promptsView.findViewById(R.id.iv_right);
ArrayList<String> switches = new ArrayList<String>();
iv_right.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String room_id=pref.getString("roomid","");
String serverURL = "http://dashboard.droidhomes.in/api/module?room_id=" + room_id;
// Use AsyncTask execute Method To Prevent ANR11 Problem
new GetallModules().execute(serverURL);
}
});
for (int i = 0; i < response.getModule().length; i++) {
tv_roomname.setText(response.getModule()[i].getRoom_title());
for (int j = 0; j < response.getModule()[i].getSwitches().length; j++) {
if (response.getModule()[i].getModule_name().equals(response.getModule()[i].getSwitches()[j].getModule_name_switches())) {
switches.add(response.getModule()[i].getSwitches()[j].getSwitch_name());
}
}
}
ToggleButtonListAdapter t1=new ToggleButtonListAdapter(MainActivity.this, switches);
list_modules.setAdapter(t1);
t1.notifyDataSetChanged();
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} else {
Toast.makeText(getApplicationContext(), "No module defined for this room!!!!!!", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), "status:-" + response.getStatus(), Toast.LENGTH_SHORT).show();
}
}
}
}
Same Scenario like this.
please help me!!

Could not get the value from Edit Text element

Fantastic morg. Below this code to get data from mysql database and displayed into the EditText element.There is no problem with getting data from db its working good using this asyn tesk new checkUserPermission().execute("");.
Problem is
I want to make some calculation from code and dispaly in another Edittext. so i need values thats why i get data from db.while OnCreate() to get the data from db(its working). whenever i call this calculatePL(); method i could not get value.
LOGCAT:
System.out: Empty Value
Why its empty or something. but above my edittext elements hold the
values.
...some declaration of variables and etc....
public void onCreate(Bundle SavedInstanceState) {
super.onCreate(SavedInstanceState);
setContentView(R.layout.five_activity);
new checkUserPermission().execute(""); //call here
calculatePL();//call the method
}
class checkUserPermission extends AsyncTask<String, String, String> {
private ProgressDialog Dialog = new ProgressDialog(Five_Activity.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Please wait..");
Dialog.show();
super.onPreExecute();
userid = (TextView)findViewById(R.id.userID);
uid = userid.getText().toString();
System.out.println(uid);
}
#Override
protected String doInBackground(String... arg0) {
ArrayList<NameValuePair> values = new ArrayList<NameValuePair>();
values.add(new BasicNameValuePair("userid", uid));
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.13:8090/stat_api/shiftClose.php");
httppost.setEntity(new UrlEncodedFormEntity(values));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is2 = entity.getContent();
Log.i("TAG", "Connection Successful");
} catch (Exception e) {
Log.i("TAG", e.toString());
//Invalid Address
}
try {
BufferedReader reader2 = new BufferedReader(new InputStreamReader(is2, "iso-8859-1"), 8);
StringBuilder sb2 = new StringBuilder();
while ((line2 = reader2.readLine()) != null) {
sb2.append(line2 + "\n");
}
is2.close();
result2 = sb2.toString();
JSONObject json_data2 = new JSONObject(result2);
code2=(json_data2.getString("code"));
Allvalues = code2;
String[] splited = Allvalues.split("\\s+");
Totalkm=splited[0];
discountamt=splited[1];
receviedamt=splited[2];
totalamt=splited[3];
expen=splited[4];
//Log.d("Splited String ", "Splited String" + totalamt+expen);
runOnUiThread(new Runnable() {
#Override
public void run() {
totkm.setText(Totalkm);
discount.setText(discountamt);
recamt.setText(receviedamt);
totamt.setText(totalamt);
expenses.setText(expen);
}
});
Log.i("TAG", "Result Retrieved");
} catch (Exception e) {
Log.i("TAG", e.toString());
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result){
// Close progress dialog
Dialog.dismiss();
}
}
public void calculatePL(){
try {
String a_value =totamt.getText().toString().trim();
System.out.println(a_value);
}catch(NumberFormatException numberEx)
{
System.out.println(numberEx);
}
}
Your checkUserPermission executes in background. And immediately you are calling calculatePL() so your main thread is not waiting for checkUserPermission execution to complete.
What you need to do is, make wait your main thread so that after full execution of checkUserPermission calculatePL() will get called. You can achieve it by adding ProgressDialog. Show the ProgressDialog in onPreExecute() and dismiss it in onPostExecute()
Hope it will do your job.
Override protected void onPostExecute in your asyncTask and call calculatePl() here. And you should set Edittext's text in onPostExecute too, because this method is main thread and you don't need to use runOnUIThread.
EDIT with example code:
class checkUserPermission extends AsyncTask<String, String, String> {
private ProgressDialog Dialog = new ProgressDialog(Five_Activity.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Please wait..");
Dialog.show();
super.onPreExecute();
userid = (TextView)findViewById(R.id.userID);
uid = userid.getText().toString();
System.out.println(uid);
}
#Override
protected String doInBackground(String... arg0) {
ArrayList<NameValuePair> values = new ArrayList<NameValuePair>();
values.add(new BasicNameValuePair("userid", uid));
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.13:8090/stat_api/shiftClose.php");
httppost.setEntity(new UrlEncodedFormEntity(values));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is2 = entity.getContent();
Log.i("TAG", "Connection Successful");
} catch (Exception e) {
Log.i("TAG", e.toString());
//Invalid Address
}
try {
BufferedReader reader2 = new BufferedReader(new InputStreamReader(is2, "iso-8859-1"), 8);
StringBuilder sb2 = new StringBuilder();
while ((line2 = reader2.readLine()) != null) {
sb2.append(line2 + "\n");
}
is2.close();
result2 = sb2.toString();
JSONObject json_data2 = new JSONObject(result2);
code2=(json_data2.getString("code"));
Allvalues = code2;
} catch (Exception e) {
Log.i("TAG", e.toString());
e.printStackTrace();
}
return Allvalues;
}
protected void onPostExecute(String result){
String[] splited = result.split("\\s+");
Totalkm=splited[0];
discountamt=splited[1];
receviedamt=splited[2];
totalamt=splited[3];
expen=splited[4];
totkm.setText(Totalkm);
discount.setText(discountamt);
recamt.setText(receviedamt);
totamt.setText(totalamt);
expenses.setText(expen);
// Close progress dialog
Dialog.dismiss();
calculatePL();
}
}
Make sure totamt is declared as a global. Try logging the value of totamt or an object of the same. Finally check where you have declared it.

Progress Bar not visible with Stand alone asynctask

I am trying to fetch some data from Web Server through JSON. I am using asynctask to do so. Normally it is taking 5-10 seconds to be shown in my ListView.
Hence I want to put spinner progress bar. My code is working fine only problem is the progress bar is not visible.
MyActivity code to call asyntask
try{
JSONObject output = new AsyncTaskJsonParse(this,status, A, B, city).execute().get();
try {
JSONObject output = new AsyncTaskJsonParse(ListViewDisplay.this,status, bgrp, antigen, city).execute().get();
JSONObject src = output.getJSONObject("data");
String flag = output.getString("success");
String flagmsg = output.getString("message");
if (flag == "1") {
JSONArray jarr_name = new JSONArray(src.getString("name"));
JSONArray jarr_fathername = new JSONArray(src.getString("fathername"));
JSONArray jarr_moh = new JSONArray(src.getString("moh"));
JSONArray jarr_city = new JSONArray(src.getString("city"));
JSONArray jarr_phone = new JSONArray(src.getString("phone"));
int n = jarr_name.length();
name_array = new String[n];
fathername_array = new String[n];
moh_array = new String[n];
phone_array = new String[n];
city_array = new String[n];
for (int i = 0; i < n; i++) {
name_array[i] = (String) jarr_name.get(i);
fathername_array[i] = (String) jarr_fathername.get(i);
moh_array[i] = (String) jarr_moh.get(i);
phone_array[i] = (String) jarr_phone.get(i);
city_array[i] = "Vadodara";
Log.d("Inside StringArray", i + "");
}
String msg = src.getString("name");
list = (ListView) findViewById(R.id.listView);
CustomListAdapter custAdaptor = new CustomListAdapter(this, name_array, fathername_array, mohalla_array, city_array, phone_array);
list.setAdapter(custAdaptor);
}else
{
Toast.makeText(this, "Data not found" + flagmsg, Toast.LENGTH_LONG).show();
}
}catch(ExecutionException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(InterruptedException e)
{
e.printStackTrace();
}catch(JSONException je)
{
}
Standalone asyntask with progressbar code
public class AsyncTaskJsonParse extends AsyncTask<String, String, JSONObject>
{
String A,B;
private String url = "abc.com/check.php";
List<NameValuePair> param=new ArrayList<NameValuePair>();
private Context context;
private ProgressDialog progress;
public AsyncTaskJsonParse(Context context,String A,String B,String antigen,String city)
{
this.A=A;
this.B=B;
this.city=city;
this.context=context;
progress=new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.e("In preexecution ", "Preexecution 1");
progress.setMessage("Processing...");
progress.setIndeterminate(true);
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.setCancelable(true);
Log.e("In preexecution azam", "Preexecution 2");
progress.show();
if(progress.isShowing())
{
Log.d("In preexecution ", "Showing 2");
}
}
//rest of code i.e. doInBackground and postexecute come after this.
#Override
protected JSONObject doInBackground(String... arg0) {
// TODO Auto-generated method stub
try
{
JsonParsor parse=new JsonParsor();
Log.d("diInbackgrnd ","Dialog box");
jsonobj = parse.getJSONFromUrl(url, param);
}
catch(Exception e)
{
Log.e(TAG, " "+e );
}
return jsonobj;
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//pDialog.dismiss();
if(progress.isShowing())
{
Log.e("In onPost ", "Showing 2");
}
progress.dismiss();
}
}
In my log I can see the message "In preexecution Showing 2". And the appliaction is working as expected but the Spinner progressbar is not visible.
Note: I did not add any progressbar component in any xml file. Does i need to add it? if yes then where and how?
class JsonParser.java
public class JsonParsor {
final String TAG = "JsonParser.java";
static InputStream is = null;
static JSONObject jObj = null;
static String str = "";
public JSONObject getJSONFromUrl(String url,List<NameValuePair> params) {
try {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
post.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try
{
BufferedReader br=new BufferedReader(new InputStreamReader(is,"iso-8859-1"), 8);
StringBuilder builder=new StringBuilder();
String line=null;
while((line=br.readLine())!=null)
{
builder.append(line + "\n");
}
is.close();
str=builder.toString();
}
catch(Exception e)
{
}
try {
jObj=new JSONObject(str);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jObj;
}
}
I suspect your problem is that your AsyncTask finishes immediately as parse.getJSONFromUrl... is also Async. So whats happening is that progress.dismiss(); in onPostExecute invoked also immediately.
Try removing progress.dismiss(); from onPostExecute and see what happens
This should work. But without the progress.setMessage("Processing...");
You can still set that.
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(getActivity(),R.style.MyTheme);
dialog.setCancelable(false);
dialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
dialog.show();
}

Using AsyncTask makes the app slower

I had this problem and you suggested to use AsyncTask or Service.
So now i'm using for the first time an AsyncTask class in which i add code for downloading and parsing a JSON file. Here is the code:
public class HomePage extends Activity{
private Database db = new Database(this);
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.homepage);
new DownloadDataFromServer().execute(new String[] { "http://www.example.com/data.json" });
}
protected void onDestroy() {
super.onDestroy();
db.close();
}
// Async Task Class
private class DownloadDataFromServer extends AsyncTask<String, Integer, String> {
ProgressDialog dialog;
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(HomePage.this);
dialog.setIndeterminate(false);
dialog.setMax(100);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(true);
dialog.setTitle("Download JSON");
dialog.setMessage("Please wait..");
dialog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... urls) {
int count = 0;
int lenghtOfFile = 0;
// JSON DOWNLOADING AND PARSING
SQLiteDatabase dbr = db.getReadableDatabase();
try {
StrictMode.ThreadPolicy policy= new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(urls[0]);
request.addHeader("Cache-Control", "no-cache");
long id = -1;
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
InputStreamReader in = new InputStreamReader(entity.getContent());
BufferedReader reader = new BufferedReader(in);
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line=reader.readLine()) != null) {
stringBuilder.append(line);
}
JSONArray jsonArray = new JSONArray(stringBuilder.toString());
SQLiteDatabase dbWrite = db.getWritableDatabase();
ContentValues values = new ContentValues();
dbr.delete("users", "1", null);
long total = 0;
lenghtOfFile = jsonArray.length();
for (int i = 0; i < lenghtOfFile; i++) {
JSONObject jObj = (JSONObject) jsonArray.getJSONObject(i);
values.put("_id", jObj.optString("id").toString());
values.put("city", jObj.optString("city").toString());
values.put("name",jObj.optString("name").toString());
id = dbWrite.insert("users", null, values);
count++;
total += count;
onProgressUpdate((int) ((total * 100) / lenghtOfFile));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return lenghtOfFile+"";
}
protected void onProgressUpdate(Integer... progress) {
dialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
if (Integer.parseInt(result) < 0) {
Toast.makeText(getBaseContext(), "Failed!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), result + " users", Toast.LENGTH_SHORT).show();
}
dialog.dismiss();
}
}
}
It takes long time to reach 100%, almost 1 minute!
Besides the progress bar hangs on 0% for a while and then it shows only 100%.
What could be the problem?
It happens because each insert() makes its own transaction in DB. You have to wrap all your insert() invokations in one transaction like this:
dbWrite.beginTransaction();
try {
//put all insert() here
dbWrite.setTransactionSuccessful();
}catch {
//Error in between database transaction
}finally {
dbWrite.endTransaction();
}
Good luck with it! :)
Also, you should use publishPorgress method for update ProgressDialog instead invoke onProgressUpdate directly
To update the progress of the AsyncTask you should call the publishProgress method.
DON'T call onPublishProgress directly.

Android Asynctask: wait for entire computation without blocking UI thread

I have almost finished my project, only one thing remain to improve.
My app is a music quiz, that retrieves all the informations about author, song title, previewUrl ecc. from the Itunes Store using the apposite Search API.
When a user choose a genre to play with, I must say to the user to wait for 4-5 seconds because of the computation that fills the List containing all the informations.
I call the Asynctask that retrieve these informations like this:
JsonCanzoni recuperoCanzoni = new JsonCanzoni(arrayGenere,Canzone.this);
try {
recuperoCanzoni.execute().get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The class (extends Asynctask) that do these operation is the following:
class JsonCanzoni extends AsyncTask<Void, Void, Void>
{
List<String> canzoni = new ArrayList<String>(5);
ProgressDialog pDialog;
int[] arrayGenere;
Context context;
public JsonCanzoni(int[] arrayGenere,Context context)
{
this.arrayGenere = arrayGenere;
this.context = context;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Preparazione round...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected Void doInBackground(Void... params)
{
try
{
int randomLookupId = 0;
JSONObject obj;
JSONArray jsonArray;
for(int i = 0; i < 10; i++)
{
canzoni = new ArrayList<String>();
Log.d("GENERE", arrayGenere.toString());
obj = getJSONObject(scegliClassifica(arrayGenere));
jsonArray = obj.getJSONArray("resultIds");
Log.d("dimensione JsonArray", String.valueOf(jsonArray.length()));
try
{
randomLookupId = new Random().nextInt(jsonArray.length()-1);
}
catch(IllegalArgumentException errore)
{
new AlertDialog.Builder(context)
.setTitle("Connessione non attiva!")
.setMessage("Connessione di rete debole, uscita dal programma!");
}
Log.d("randomLookupID", String.valueOf(randomLookupId));
JSONObject finalObj = getJSONObject("http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
Log.d("URL","http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
while(finalObj.getJSONArray("results").length() == 0)
{
Log.d("Array VUOTO!!","Non รจ possibile!!!!");
randomLookupId = new Random().nextInt(jsonArray.length()-1);
Log.d("randomID rigenerato", String.valueOf(randomLookupId));
finalObj = getJSONObject("http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
Log.d("URL Rigenerato","http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
}
JSONArray finalJsonArray = finalObj.getJSONArray("results");
JSONObject returnObj = finalJsonArray.getJSONObject(0);
Log.d("returnObj.length",String.valueOf(returnObj.length()));
canzoni.add(returnObj.getString("previewUrl"));
canzoni.add(returnObj.getString("artistName"));
canzoni.add(returnObj.getString("trackName"));
canzoni.add(returnObj.getString("artistViewUrl"));
canzoni.add(returnObj.getString("artworkUrl100"));
// GTTapp app=(GTTapp) ((Activity)context).getApplication();
// app.dieciCanzoni;
Canzone.dieciCanzoni.add(i, new ArrayList<String>(canzoni));
}
}
catch (JSONException ignored)
{
ignored.getCause();
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private String scegliClassifica(int[] arrayGenere)
{
int randomArrayPosition = new Random().nextInt(arrayGenere.length);
return "http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/charts?cc=us&g="+arrayGenere[randomArrayPosition]+"&name=Songs&limit=200";
}
JSONObject getJSONObject(String url) throws IOException, MalformedURLException, JSONException
{
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
InputStream in = conn.getInputStream();
try
{
StringBuilder sb = new StringBuilder();
BufferedReader r = new BufferedReader(new InputStreamReader(new DoneHandlerInputStream(in)));
for (String line = r.readLine(); line != null; line = r.readLine())
{
sb.append(line);
}
return new JSONObject(sb.toString());
}
finally
{
in.close();
}
}
}
THE PROBLEM: Using the .get() method make the app waiting for the entire computation of the AsyncTask, but it block the UI thread too!! So the user will remain with a black screen for 5 secs or more, and that's not a good thing!
If I don't use the .get() method, I receive an IndexOutOfBounds Exception, because I begin to play the music stream but the list is has not been filled yet.
Can you suggest me a workarund for this situation?
Thank you!
remove .get() it will block the UI till completion of the task.
Start any task like (playing video) which is dependent on AsycTask in
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
//You can start music stream here
}
The get() call is blocking. From the docs:
Waits if necessary for the computation to complete, and then retrieves its result.
What you should do is wait asynchronously the computation to finish before you start to play the music.
If you do not want to expose the asynctask outside your class, you can set a callback into your JSonCanzoni class to be called into the onPostExecute method of the asynctask.
Something like
public interface CanzoniDownloadedInterface {
public void onCanzoniDownloaded();
}
public JsonCanzoni(int[] arrayGenere, CanzoniDownloadedInterface callback, Context context){
this.arrayGenere = arrayGenere;
this.context = context;
this.callback = callback;
}
and in your onPostExecute():
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
this.callback.onCanzoniDownloaded();
pDialog.dismiss();
}
If you let your activity implement the interface, you can pass it to your class.
The onCanzoniDownloaded() implementation is where you need to start playing.
Finally I solved my problem, some advices were good and helped me a lot!
I simply moved the startActivity instruction to onPostExecute of JsonCanzoni AsyncTask, and changed some code to adapt to the new version and it's all right! ;)

Categories

Resources