AsyncTask behavior confusion - android

I have this project:
Im trying to undestand where is the problem and how can be solved, but a this simply point I really dont know where is the problem.
I have a button and a TextView.
When the button is clicked this procedure is called:
android:onClick="pulsaboton"
And the TextView show me the output.
This is Main_Activity.java
package com.example.pruebasonidos;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
public String cadena1="", cadena2="";
public TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textview01);
}
public class generamusica extends AsyncTask<String, Integer, Integer>
{
#Override
protected void onPreExecute(){
tv.setText(tv.getText().toString()+"Pre Execute");
}
#Override
protected Integer doInBackground(String...strings) {
String cadena=strings[0];
tv.setText(tv.getText().toString()+cadena);
return null;
}
#Override
protected void onPostExecute(Integer bytes){
tv.setText(tv.getText().toString()+"Post Execute");
}
}
public void pulsaboton(View v) {
cadena1="123"; cadena2="111";
tv.setText("");
new generamusica().execute(cadena1);
new generamusica().execute(cadena2);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
When pulsaboton is clicked, textview1 display this:
PreExecutePreExecute123111PostExecutePostExecute
I want this output:
PreExecute123PostExecutePreExecute111PostExecute
What is the error????

WARNING: INTERFACE MODIFICATION EXECUTED OUTSIDE OF UI THREAD!
protected Integer doInBackground(String...strings) {
...
tv.setText(tv.getText().toString()+cadena);
...
}
Why do you think AsyncTask exposes onPreExecute and onPostExecute? Couldn't you just do all of your interface work in doInBackground, before and after your async code?
In Android, the UI needs to be accessed from the main thread, the foreground thread; which doInBackground is not run in.
If you need to post updates to your UI during the execution of an AsyncTask, use the publishProgress mechanism.
Edit: "properly" accesing the interface is a lot more complex that just using onPreExecute and onPostExecute. See this blog post. Maybe you should try the Loader API, it's less troublesome.

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution..
http://developer.android.com/reference/android/os/AsyncTask.html
You are updating ui on the background thread which is not possible. You need to update ui on the ui thread
In doInBackground()
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
String cadena=strings[0];
tv.setText(tv.getText().toString()+cadena); ;
}
});

For your required output Call these two lines in onPostExecute,
cadena2="111";
new generamusica().execute(cadena2);
And dont try to update the UI in background thread.
See This for more info

Related

Android setContentView suppressed by AsyncTask in onCreate

I want to show some message and a progress bar while my app initializes.
I need to insert some dictionaries of words into a SQLite database the first time my app is run. To do this I have an AsyncTask which opens my SQLiteOpenHelper and closes it again, just so the database initialization is done once.
private class AsyncDbInit extends AsyncTask<Void, Void, Void> {
private Context context;
private Intent intent;
public AsyncDbInit(Context context, Intent intent){
this.context = context;
this.intent = intent;
}
#Override
protected Void doInBackground(Void... params) {
DatabaseHandler db = new DatabaseHandler(this.context);
db.close();
return null;
}
#Override
protected void onPostExecute(Void param) {
context.startActivity(this.intent);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... params) {}
}
This AsyncTask is called in my onCreate() method, but I've also tried to run it from onStart() and onResume() without succes.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dispatcher);
... //some code finding the right intent
new AsyncDbInit(this, nextIntent).execute();
}
Somehow this last line, which calls the AsyncTask, stops my UI from showing up; the screen just stays blank until the AsyncTask is completed and the new activity is started.
When I comment that line out, the UI shows up just fine.
The only thing I can come up with is that the SQLiteOpenHelper somehow blocks the UiThread, but I couldn't find anything about that either.
In the AsyncTask we have some methods. Just like in doInBackground() we do the things we wants to be done in the background and there are two methods also whch are onPreExecute() and onPostExecute(). Create and progress dialog and show the dialog in onPreExecute() method and dismiss it in onPostExecute() method.
Try using AsynTask.executeOnExecutor() with the thread pool executor. If this works, it means something involved with loading your UI is also using an AsyncTask. AsyncTasks by default run sequentially on a single work thread and this can introduce contention. This serial execution is often what you want, but not always.
Does you UI use any libraries to load strings or other content? Can you provide your layout XML?

Pass value from thread to main activity

I've been searching this online for a long time. Maybe what I'm doing here is wrong.
I have written a thread class in a separate file from MainActivity.java. Because both the thread and the main activity are relatively long, I decided to separate them into different files.
I wanted to pass some value generated from the thread class to the main activity. Initially I want to use handlers. But because the thread is in a different class to the main activity. It has no idea the handler I defined in the main activity.
public class mythread implements Runnable{
#Override
public void run(){
result = result_from_some_task();
}
}
This is the basic structure of my thread class and I want to pass result back to the main activity. I've looked at many examples, most of them the thread is within the main activity class and the handlers defined can be easily referred to.
Intent doesn't seems to be applicable. Does anyone have any idea on how such operations can be done?
Thanks in advance.
Make parameterized constructor of AnotherClass and when you make of object of AnotherClass then simply pass object of MainActivity into that constructor and inside AnotherClass class where you want to call MainActivity's method then simply call that method from that Object.
check following code :
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AnotherClass object= new AnotherClass (this);
object.start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void makeSomeCalculation() {
//logic to change some UI
}
}
and check Another class :
public class AnotherClass extends Thread {
MainActivity mainActivity;
public AnotherClass (MainActivity mainActivity) {
// TODO Auto-generated constructor stub
this.mainActivity = mainActivity;
}
public void run() {
//write other logic
mainActivity.makeSomeCalculation();
//write other logic
}
}
This may not be what you are looking for so consider it as suggestion to avoid long term headaches.Try EventBus. This a library to communicate easily between various components in Android.
you need a handler in your activity. and when your thread finishes , you then dispatch a message to handler , notifying that thread execution finished. see here for example.
you can also use interface for this. see here for example. In answer, he use interface to notify from asyntask. you can do same for thread.
Your need to run the activity function within runOnUiThread.
mainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mainActivity.makeSomeCalculation();
}
});

Calling web service using Async task in android?

I have my separate web service class in which i just pass response method, url and array list of data which is required for making the request and getting the response. I call this web service in my login activity like this
JifWebService webServices = new JifWebService();
webServices.Execute(RequestMethod.POST,
Jifconstant.LOGIN_URL, null, logindata);
loginResponse = webServices.getResponse();
loginResponseCode = webServices.getResponseCode();
In this login data is a array list which contains some data. Now i want to call this web service in background using async task. But i am just not getting it correctly. My web service logic is written in totally different java file and its working fine but i want to call my web service methods inside async task.enter code here
You can try below code for Async Task and also call web service in doInBackground:
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
public class AsyncExample extends Activity{
private String url="http://www.google.co.in";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new AsyncCaller().execute();
}
private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog pdLoading = new ProgressDialog(AsyncExample.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("Loading...");
pdLoading.show();
}
#Override
protected Void doInBackground(Void... params) {
//this method will be running on a background thread so don't update UI from here
//do your long-running http tasks here, you don't want to pass argument and u can access the parent class' variable url over here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//this method will be running on UI thread
pdLoading.dismiss();
}
}
}
Done

Updating an Activity from an AsyncTask

So I'm an iOS developer learning android, and I'm having a difficult time understanding some things. Right now I have a datamanager class. In that class it has an AsyncTask to update the data. OnPreExecute I pop an activity to show it is updating. I understand I could use extras to pass initial information to the UpdateActivity. My problem is I'm not sure how to send new information in OnProgressUpdate. Here is my code widdled down:
private class myTask extends AsyncTask<Integer,String,Void>{
#Override
protected void onCancelled() {
super.onCancelled();
isUpdating = false;
}
#Override
protected Void doInBackground(Integer... params) {
//My BG Code
}
#Override
protected void onPostExecute(Void result) {
// TODO Remove updating view
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
Intent myIntent = new Intent(mContext,UpdateActivity.class);
mContext.startActivity(myIntent);
}
}
AsyncTask is designed to work best when nested in an Activity class.
What makes AsyncTask 'special' is that it isn't just a worker thread - instead it combines a worker thread which processes the code in doInBackground(...) with methods which run on the Activity's UI thread - onProgressUpdate(...) and onPostExecute(...) being the most commonly used.
By periodically calling updateProgress(...) from doInBackground(...), the onProgressUpdate(...) method is called allowing it to manipulate the Activity's UI elements (progress bar, text to show name of file being downloaded, etc etc).
In short, rather than firing your 'update' Activity from an AsyncTask, your update Activity itself should have a nested AsyncTask which it uses to process the update and publish progress to the UI.
You have two options:
1) Pass an instance of activity to your AsyncTask constructor in order to invoke some method on it:
new MyTask(this).execute();
So, you can do:
public MyTask (Activity activity) {
this.activity = activity;
}
public void onPostExecute(...) {
activity.someMethod();
}
2) Pass a Handler instance and send message from onPostExecute() to the activity.

Whats wrong with my Thread()-code?

I have a question regarding an Android application. I want to, later on, create a game and i am currently trying out classes and functions that I need to understand.
At the moment im trying to get a grip of how to use threads in a good way, but my application is "force closing" when i touch the button.
For this test application, all have on the screen is one TextView and one button.
The button is calling threadStart() when pressed. (onClick in xml)
And what i want it to do is to create a thread which increases the variable value by 1 and then report to the UI thread which then update the textview with the new value.
Can someone see what i am doing wrong with this small pice of code?
package com.weldeborn.tc;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
public class ThreadCounter extends Activity {
TextView txtCounter1;
int value=0;
final Handler mHandler = new Handler();
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResult();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtCounter1 = (TextView) findViewById(R.id.counter1);
}
protected void threadStart() {
Thread t = new Thread() {
public void run() {
doSomething();
mHandler.post(mUpdateResults);
}
};
t.start();
}
private void doSomething() {
value = value+1;
}
private void updateResult() {
txtCounter1.setText(value);
}
}
My code is based on an example from Android Developer: The Common Tasks and how to do them section under the "Handling Expensive Operations in the UI Thread" heading.
I am thankful for any help.
setText doesn't work correctly when you pass an integer, directly. Try converting it to String before:
txtCounter1.setText(String.valueOf(value));
Also, check this answer about the usage of threads that need to update the UI.
if threadStart is your onClick the signature needs to be
public void threadStart(View v)

Categories

Resources