I want to display a Progress Dialog while I have two threads running one after the other, but my data structure that I use gets populated via the threads, becomes null. Thus I used thread.get() method to wait for the thread to be finished....not sure how I can get around this here is an example of one of my Async Threads:
private void performDetailSearch(String reference) {
String addplus = searchterm.replace(" ", "+");
RestClientDS restpSd = new RestClientDS();
String url = PLACES_DETAILS_URL +"reference="+ reference + "&sensor=false&key=" + API_KEY;
Log.d("url",url);
String[] URL = {url};
restpSd.execute(URL);
try {
restpSd.get();
}
catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
catch (ExecutionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Use AsyncTask instead of Thread and call another task after one gets completed.
AsyncTask can be called this way new FetchData().execute();
private class FetchData extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
//do your background work
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
//call the another asynctask from here.
// new FetchData2().execute();
}
}
}
Related
I extended the Application class in order to create singleton-like object in android.
in this object I have all the HTTP work with my server, and all the other activities can access it and call methods to GET, POST etc.
Code:
public class HttpManagerInstance extends Application {
private HttpClient httpClient;
private HttpGet get;
#Override
public void onCreate() {
httpClient = new DefaultHttpClient();
get = new HttpGet("http://10.100.102.9:8000/users/");
super.onCreate();
}
public Void getUsers() throws Exception {
new executeRequest().execute(get);
return null;
}
private class executeRequest extends AsyncTask<HttpRequest, Void, Integer> {
#Override
protected Integer doInBackground(HttpRequest... params) {
// TODO Auto-generated method stub
HttpRequest request = params[0];
HttpResponse response;
String result="";
try {
response = httpClient.execute((HttpUriRequest) request);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseCode;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
switch (result) {
case HttpStatus.SC_OK:
// request was fine
// Here I want to updated the GUI of the activity that called this method.
break;
}
}
}
}
This is how I call the method from the Activity:
HttpManagerInstance sampleApp = (HttpManagerInstance)getApplicationContext();
sampleApp.getUsers();
Again - I want to access the UI of the Activity that called the method to put an REQUEST ACCEPTED message.
Maybe pass a context? any ideas?
I'd create a listener:
public class HttpManagerInstance extends Application {
private HttpClient httpClient;
private HttpGet get;
public interface ResponseListener{
public void onSuccess(Object data);
}
#Override
public void onCreate() {
httpClient = new DefaultHttpClient();
get = new HttpGet("http://10.100.102.9:8000/users/");
super.onCreate();
}
public Void getUsers(ResponseListener listener) throws Exception {
new executeRequest(listener).execute(get);
return null;
}
private class executeRequest extends AsyncTask<HttpRequest, Void, Integer> {
private ResponseListener mListener;
public executeRequest(ResponseListener listener){
this.mListener = listener;
}
#Override
protected Integer doInBackground(HttpRequest... params) {
// TODO Auto-generated method stub
HttpRequest request = params[0];
HttpResponse response;
String result="";
try {
response = httpClient.execute((HttpUriRequest) request);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseCode;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
switch (result) {
case HttpStatus.SC_OK:
// request was fine
// Here I want to updated the GUI of the activity that called this method.
if(this.mListener != null) mListener.onSuccess(whatEverDataYouWant);
break;
}
}
}
}
Then, in your activity:
HttpManagerInstance sampleApp = (HttpManagerInstance)getApplicationContext();
sampleApp.getUsers(new ResponseListener(){
public void onSuccess(Object data){
//update your ui!
}
});
The short answer is you can't directly reference to the UI from another activity. My advice would be for you to set up a callback on your Application class and call in on executeRequest#onPostExecute then implement that callback on your Activity and update your UI from there.
If you need help to implement the callback check this question
If you need to show message is good option the Dialog Class or the Toast Class, you can see more info are here:
Dialogs: http://developer.android.com/guide/topics/ui/dialogs.html
Toasts: http://developer.android.com/guide/topics/ui/notifiers/toasts.html
But if you want to access or modify a control in your actual activity, then use Runnable class, and context.runOnUiThread() method if you work inside AsyncTask. The real problem is that you can't change UI in a AsyncTask using declaration of the controls. You need to throw a Runnable process to communicate with activity!!. For example:
context.runOnUiThread(new Runnable() {
public void run() {
//Declaration of variables
TextView MyTextView = (TextView) context.findViewById(R.id.txtvMyControl);
MyTextView.setText("My title");
}
}
If I can helps you say me, good luck!
Goodmorning,
I have a button on my android app that launches a search on the web (through google endpoints) through an AsyncTask. My problem is that the button does not "unclick" until the AsyncTask is completed, which may take several seconds. When the internet connection is slow, this even makes the application crash, in any case the application is completely stuck until the AsyncTask is completed. Now the reason for using AsyncTask was exactly to eliminate this problem, so I don't really get what happens!
Here is the OnClickListener:
SearchListener = new OnClickListener() {
#Override
public void onClick(View v) {
String cname=TextCourse.getText().toString();
if (!cname.isEmpty()){
try {
CollectionResponseWine listavini= new QueryWinesTask(messageEndpoint,cname,5).execute().get();
} catch (InterruptedException e) {
showDialog("Errore ricerca");
e.printStackTrace();
} catch (ExecutionException e) {
showDialog("Errore ricerca");
e.printStackTrace();
}
} else{
showDialog("Inserisci un piatto");
}
}
};
and here is the AsyncTask that is being called:
private class QueryWinesTask
extends AsyncTask<Void, Void, CollectionResponseWine> {
Exception exceptionThrown = null;
MessageEndpoint messageEndpoint;
String cname;
Integer limit;
public QueryWinesTask(MessageEndpoint messageEndpoint, String cname, Integer limit) {
this.messageEndpoint = messageEndpoint;
this.cname=cname;
this.limit=limit;
}
#Override
protected CollectionResponseWine doInBackground(Void... params) {
try {
CollectionResponseWine wines = messageEndpoint.listwines().setCoursename(cname).setLimit(limit).execute();
return wines;
} catch (IOException e) {
exceptionThrown = e;
return null;
//Handle exception in PostExecute
}
}
protected void onPostExecute(CollectionResponseWine wines) {
// Check if exception was thrown
if (exceptionThrown != null) {
Log.e(RegisterActivity.class.getName(),
"Exception when listing Messages", exceptionThrown);
showDialog("Non ci sono vini associati al tuo piatto. Aggiungine uno!");
}
else {
messageView.setText("Vini piu' votati per " +
cname + ":\n\n");
for(Wine wine : wines.getItems()) {
messageView.append(wine.getName() + " (" + wine.getScore() + ")\n");
}
}
}
}
...execute().get() is blocking. It makes UI thread wait for Task to complete.
Don't do get(). Use onPostExecute() to get the result (wines) of task and update the UI.
This is my code: (Some random text to complete question osdifhgsoid hgodfhgo hsdhoigifdshgnvfa oidvojd nobndisfn vbjobsf).
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
protected Long doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x)
{
textIn.setText("shit! " + x.toString());
}
long i = 10;
return i;
}
}
(Some random text again to complete question(stupid system) dpfgojd ipgsdigjsidoignsdog
public void Listen(){
int count = 0;
TextView msg = MyActivity.msg;
ServerSocket server;
Socket client;
try {
server = new ServerSocket(9797);
Log.d("My log", "server started");
Log.d("My log", "waiting for connnections");
while (started) {
try{
msg.setText("waiting for connection"); <=== here crashing
client = server.accept();
count++;
Log.d("My Log", "Connected");
Log.d("My Log", "aha" + count);
int i = 0;
String data = null;
byte[] bytes = new byte[1024];
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
while (is.available() == 0) {
try{
Thread.sleep(50);
}catch (Exception cc){}
}
is.read(bytes, 0, is.available());
os.write("hala".getBytes());
client.close();
}catch (Exception cc)
{
cc.toString();
}
}
} catch (Exception el) {
el.printStackTrace();
}
}
(Some random text to complete question). Please help
change it via the onPostExecute method!
The purpose of an AsyncTask is to do a long running task in a separate thread and then communicate the result back to the UI thread via onPostExecute().
Also, I'm not sure why you use Long as your return value since you do not seem to be using it. A much better solution would be to have Void as return value and save the exception and use that as an indicator if anything went wrong:
private class DownloadFilesTask extends AsyncTask<String, Integer, Void> {
private Exception exception = null;
#Override
protected Void doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x) {
exception = x;
}
}
#Override
public void onPostExecute(Void result) {
if(exception != null) {
textIn.setText("shit! " + exception.toString());
}
else {
// long running task was completed successfully
}
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed.
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
Good idea would be to return a String in doInBackground(), say exceptionCatched. You can set it to Exception title in catch() block and then in onPostExecuted() just check if(!TextUtils.isEmpty(exceptionCatched)) textIn.setText(exceptionCatched); That's it!
private class DownloadFilesTask extends AsyncTask<Void, Void,Long>{
#Override
protected Long doInBackground(Void... params) {
publishProgress(progress);
//calculate progress and value from your downloading logic
try {
} catch (Exception e) {
return (long) 0;
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
//dis method run deafult on UI thread , so every time u publish ur onProgressUpdate will be called and update ur text here
}
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
if(result==0){
//error occured
}
}
// in case of exception return the result as long value to promt to onPostExceute()
I'm guessing runOnUiThread. You can't update the UI from any other thread than the UI thread.
In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.
If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.
Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):
#EActivity(R.layout.layout_splash)
#RoboGuice
public class SplashScreenActivity extends Activity {
#Inject
private AvtopoiskParserImpl parser;
#Bean
BrandsAndRegionsHolder brandsAndRegionsHolder;
#ViewById(R.id.splash_progress)
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
}
#Background
protected void loadData() {
publishProgress(10);
LinkedHashMap<String, Integer> brands = null;
try {
brands = parser.getBrands();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(50);
LinkedHashMap<String, Integer> regions = null;
try {
regions = parser.getRegions();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(70);
populateData(brands, regions);
}
#UiThread
protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
brandsAndRegionsHolder.brandsMap = brands;
brandsAndRegionsHolder.regionsMap = regions;
publishProgress(100);
startActivity(intent);
finish();
}
#UiThread
void publishProgress(int progress) {
progressBar.setProgress(progress);
}
}
parser.getBrands() and parser.getRegions() are loading data from the web.
I want to do something like this:
boolean repeatRequest = true;
while (repeatRequest) {
try {
brands = parser.getBrands();
repeatRequest = false;
} catch (IOException e) {
Log.e(e.getMessage());
repeatRequest = showErrorDialog();
}
}
But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread.
I believe that it should be standard approach of doing so, but didn't manage to find it.
Any ides how can I implement this?
The best way is to use AsyncTask.
private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
private ProgressDialog mProgress;
protected Object doInBackground(Void... params) {
// This method runs in background
Object result = null;
try {
result = parser.parse();
} catch (Exception e) {
result = e.getMessage();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
// This method runs in UI thread
mProgress.setProgress(progress[0]);
}
protected void onPreExecute() {
// This method runs in UI thread
mProgress = new ProgressDialog(context);
mProgress.show();
}
protected void onPostExecute(Object result) {
// This method runs in UI thread
mProgress.dismiss();
if (result instance of String) {
// Here you can launch AlertDialog with error message and proposal to retry
showErrorDialog((String) result);
} else {
populateData(result);
}
}
}
I have a base class of an activity and a sub class which extends the base class. The superclass has a async task to perform some action. I call this by running it on the ui thread since otherwise it throws an IllegalInitializerError:
superclass.this.runOnUiThread(new Runnable() {
public void run() {
String p="";
try {
p=new asynctasker().execute().get();
}
}
}
In my async task:
protected void onPreExecute()
{
// TODO Auto-generated method stub
super.onPreExecute();
//showDialog();
Log.d("Now","Inside right now");
dialog = ProgressDialog.show(class_create_event.this, "Loading1", "Please Wait");
}
However the dialog is displayed almost at the end of the request. The I am in part is printed correctly. I know that something is blocking my ui thread. But if I dont call the async task from the UI thread it throws an illegal initializer error. Is there any way out?
You don't need to have UIthread for calling AsyncTask
Call it like this way
FetchRSSFeeds async = new FetchRSSFeeds();
async.execute();
private class FetchRSSFeeds extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
// Fetch the RSS Feeds from URL
// do background process
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
// Setting data to list adaptar
setListData();
}
}
}