I am working on a android project>>>>
When i try to do any code in doInBackground() method in android ...it's not giving error but not running properly....
THis is my code...
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{
protected Bitmap doInBackground(String... urls)
{
button.setVisibility(View.VISIBLE);
return DownloadImage(urls[0]);
}
protected void onPostExecute(Bitmap result)
{
ImageView img = (ImageView) findViewById(R.id.img);
img.setImageBitmap(result);
}
}
This code work properly when i remove button.setVisibility(View.VISIBLE);
My query is can we do like visibility off or type of programming in doInBackground() method....
You must need to set visibility inside UI thread else it will never work. If you are in different thread use MessageHandler or can use runOnUiThread(using runnable) to set the visibility. for ex :
runOnUiThread(new Runnable() {
#Override
public void run() {
// set visibility here
}
});
in doInBackground() method you can't do UI Realated Operations.
If you have to do UI Related Operations use onPreExcuteMethod() or onPostExcute()i.e,
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{
protected void onPreExcute(){
// Before starting the function.
button.setVisibility(View.VISIBLE);
}
protected Bitmap doInBackground(String... urls)
{
return DownloadImage(urls[0]);
}
protected void onPostExecute(Bitmap result)
{
// after completion of the function.
// button.setVisibility(View.VISIBLE);
ImageView img = (ImageView) findViewById(R.id.img);
img.setImageBitmap(result);
}
}
i think this will work or you can you use post Excute method based on your functionality
You can put this line button.setVisibility(View.VISIBLE); in your onPreExcute() mehod of async task
You can not update your UI in doInBackground(). How to use AsyncTask in android.
You cannot update any UI elements in doInBackground() as this method is executed in a separate (non-UI) thread.
Use onPreExecute() for that
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{
protected void onPreExecute(){
button.setVisibility(View.VISIBLE);
}
protected Bitmap doInBackground(String... urls)
{
return DownloadImage(urls[0]);
}
protected void onPostExecute(Bitmap result)
{
ImageView img = (ImageView) findViewById(R.id.img);
img.setImageBitmap(result);
}
}
To work on UI in doInBackground then you need to use runOnUiThread.
runOnUiThread(new Runnable() {
public void run() {
// some code #3 (Write your code here to run in UI thread)
}
});
Thanks
Related
I am displaying a ProgressDialog in an AsyncTask, as follows.
public class DataComm extends AsyncTask<String, Void, JSONObject> {
...
ProgressDialog pd = null;
...
protected void onPreExecute() {
pd = ProgressDialog.show(activity, activity.getResources().getText(R.string.wait_please) + "\u2026", "", true);
...
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
...
pd.dismiss();
}
The PD is declared in the class which implements AsyncTask. I initialize it in onPreExecute, using the context of the activity which creates the and attempt to call pd.dismiss() at the end of doInbackground. This is called from multiple activities, in some it works, but in others I get a RuntimeException "sending message to a Handler on a dead thread".
In the failure case, I know that the activity which I used to create the PD is still alive, so I don't understand what thread has died.
The problematic call is from a class which is derived from a base class used to update a list for a class derived from ArrayAdapter. The AsyncTask is called when the ArrayAdapter needs to fill the list of options. Does this happen on some thread other than the UI main thread. I still don't see why it should die before the onPostExecute is called.
Async Task doInbackground method runs on background in separate thread other than main thread. Please check it may be because of some reason this is dying.
I think you should first create Constructor for AsyncTask DataComm ,then initialize your ProgressDialog in constructor like this:
public class DataComm extends AsyncTask<String, Void, JSONObject> {
...
ProgressDialog pd;
...
public void DataComm(Context mContext)
{
pd = new ProgressDialog(mContext);
}
protected void onPreExecute() {
this.pd.setMessage(mContext.getResources().getText(R.string.wait_please) + "\u2026");
this.pd.show();
...
}
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
...
if (pd.isShowing()) {
pd.dismiss();
}
}
Try this:
public class DataComm extends AsyncTask<String, Void, Void> {
ProgressDialog pd = null;
protected void onPreExecute() {
pd = ProgressDialog.show(activity, activity.getResources().getText(R.string.wait_please) + "\u2026", "", true);
}
protected void onProgressUpdate(Integer... progress) {
pd.setProgress(progress[0]);
}
protected void onPostExecute() {
super.onPostExecute(result);
...
activity.runOnUiThread(new Runnable() {
#Override
public void run(){
if (pd.isShowing()) {
pd.dismiss();
}
}
});
}
}
The ArrayAdapter support seems to have been the problem. Updating the list from the UpdateMap override seems to take place on a separate thread. When I put the call inside a runOnUiThread there was no more dead thread:
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
DataComm dc = new DataComm(itemFetcher, activity, pd);
dc.execute("main", "product_search","search_prefix", newFilter);
}
});
Hi so i'm trying to grab a image from a url link via AsyncTask, the function to grab the image itself work fine. but what i trying to do is to pass the src variable into a asyncTask which seems to be not working for me. the return will be blank.
here is the code:
private AsyncTask<String, Void, Drawable> task2;
Drawable profile;
public Drawable getProfile(String src){
task2 = new AsyncTask<String, Void, Drawable>() {
ProgressDialog dialog2;
InputStream is;
Drawable d;
#Override
protected void onPreExecute(){
dialog2 = new ProgressDialog(Thoughts.this, ProgressDialog.STYLE_SPINNER);
dialog2.setMessage("Loading Data...");
dialog2.setCancelable(false);
dialog2.setCanceledOnTouchOutside(false);
dialog2.show();
}
#Override
protected Drawable doInBackground(String... src) {
try
{
is = (InputStream) new URL(src[0]).getContent();
d = Drawable.createFromStream(is, "src name");
return d;
}catch (Exception e) {
e.toString();
return null;
}
}
#Override
protected void onPostExecute(Drawable result2) {
profile = result2;
dialog2.dismiss();
}
};
task2.execute(src);
return profile;
}
and i call it like this at the onCreate();
Drawable p4 = getProfile("http://..../xyz.jpg");
Drawable p5 = getProfile("http://..../xyz.jpg");
ImageView thoughtsProfilePic =(ImageView) findViewById(R.id.ivProfilePicData);
ImageView thoughtsProfilePic1 =(ImageView) findViewById(R.id.ivProfilePicData1);
thoughtsProfilePic.setImageDrawable(p4);
thoughtsProfilePic1.setImageDrawable(p5);
AsyncTask help you do an asynchronous job. In your code, I can see you return Drawable right after calling it. But at that moment, the your asynctask hasn't completed yet and drawable still null.
task2.execute(src);
return profile;
If you want set drawable resource when complete job in asynctask, just put your ImageView into your method. It should be:
public void getProfile(String src, final ImageView v){
#Override
protected void onPostExecute(Drawable result2) {
// set drawable for ImageView when complete.
v.setImageDrawable(result2);
dialog2.dismiss();
}
task2.excute(src);
//do not need return anything.
}
Use it:
ImageView thoughtsProfilePic =(ImageView) findViewById(R.id.ivProfilePicData);
getProfile("http://..../xyz.jpg", thoughtsProfilePic );
Hope this help.
Update:
There is no way to return value from asynchronous method directly, here is another choice.
First, create an interface to notify when complete job.
public interface INotifyComplete{
public void onResult(Drawable result);
}
Then your activity class should look like:
public class YourActivity extends Activity implement INotifyComplete{
private Drawable res1;
private Drawable res2;
public void onResult(Drawable result){
if(result == res1){
// do something with resource 1
ImageView thoughtsProfilePic =(ImageView) findViewById(R.id.ivProfilePicData);
thoughtsProfilePic.setImageDrawable(result);
}
if(result == res2){
// do something with resource 2
}
}
void someMethod(){
// you can use this way to call
getProfile("http://..../xyz.jpg", res1, YourActivity.this);
//or this
getProfile("http://..../xyz.jpg", res2, new INotifyComplete(){
public void onResult(Drawable result){
// result is res2, so don't need to check
}
});
}
public void getProfile(String src, final Drawable res, final INotifyComplete notify){
//don't need store asynctask instance
AsyncTask<String, Void, Drawable> task2 = new AsyncTask<String, Void, Drawable>(){
// do something ...
protected void onPostExecute(Drawable result2) {
dialog2.dismiss();
// you will set the value to your drawable then notify it when complete job
res = result2;
notify.onResult(res);
}
}
task2.excute();
}
}
write a public member function in your activity which returns drawable and just call the function in doInBackground() method of your asyncTask class.
Drawable downloadImage(){
//write code here to download image so you can return any dataType
}
now just call this function in doInBackground() method and save returned result in some variable of your activity.
like
void doInBackground(){
drawableVariable = downloadImage();
}
Edit: asyncTask is your background thread and is not UI thread so if you want to do any UI work then you will have to perform that work in UI thread by runOnUiThread() method
runOnUiThread(new Runnable() {
#Override
public void run() {
/* update your UI here for example what you are doing something */;
profile = result2;
}
});
In one of my app, I have a scenario where I need to do some background task. For doing that I am using Async Task. Also I am using custom progress dialog. Below is the layout of the custom progress dialog
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="vertical" >
<ProgressBar
android:layout_width="60dp"
android:layout_height="60dp"
android:indeterminateDrawable="#drawable/progressloader"
android:layout_gravity="center"/>
<TextView
android:id="#+id/progressMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:textSize="18sp"
android:text="Please wait...." />
</LinearLayout>
Everything works fine but when I try to set text to TextView then I am getting java NullPointerException.
AsyncTask code
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
}
#Override
protected Long doInBackground(String... urls) {
// txtView.setText("Testing"); here I am getting the error
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
MainActivity
public class SummaryActivity extends Activity {
final TextView txtView = (TextView)findbyid(R.id.progressMessage);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
new InitialSetup().execute("");
}
}
If I understand correctly, your TextView of which you want to set the text can be found in the xml file progressbar.xml (i.e. R.layout.progressbar). This TextView can be obtained once the content view has been set (using setContentView()). In your code you set it before this call is been and the code of mussharapp, he is calling it to early. Namely, he calls it after the setContentView(R.layout.accountsummary) call which does not contain the TextView. Consequently, the variable txtView will be NULL and you will get a NullPointerException.
What you should do is the following:
Set the variable txtView in onPreExecute, after setContentView is called.
Based on Paresh Mayani's explanation: Use the runOnUiThread method.
For the code look down below:
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
// Already suggested by Paresh Mayani:
// Use the runOnUiThread method.
// See his explanation.
runOnUiThread(new Runnable() {
#Override
public void run() {
txtView.setText("Testing");
}
});
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed,
Why not allowed? Because There is a only one Thread running which is UI Main Thread, and it doesn't allowed to update UI from thread process. read more info here: Painless Threading
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.
(TextView)findViewByid(R.id.progressMessage);
should only be executed after the command setContentView().
TextView txtView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
**txtView = (TextView)findbyid(R.id.progressMessage);**
new InitialSetup().execute("");
}
Also you can only change UI elements in the main UI thread. doInBackground() is not in the main UI thread. Make UI changes in onPostExecute
public class InitialSetup extends AsyncTask<String, Integer, Long> {
private Activity activity;
ProgressDialog progressDialog;
public InitialSetup(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Starting task....");
progressDialog.show();
}
#Override
protected Long doInBackground(String... urls) {
// do something
//
return 0;
}
#Override
protected void onPostExecute(Long result) {
progressDialog.dismiss();
//Perform all UI changes here
**textView.setText("Text#2");**
}
}
The explanations are correct: You are not to make UI changes in any thread except the thread which create the UI. But AsyncTask has a method called
onProgressUpdate()
which always will run in the UI Thread. So based on the modifications by dennisg your code should look like this:
private class InitialSetup extends AsyncTask<String, String, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
publishProgress("Testing");
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
#Override
protected void onProgressUpdate(String... update) {
if (update.length > 0)
txtView.setText(update[0]);
}
}
Note that the type of the parameter of onProgressUpdate is the second type given in AsyncTask!
Extra: To make your code more robust you should check if the progress dialog still exists before setting the text.
I have this code for managing some countrys on my database;
class checkCountryAsync extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
setContentView(R.layout.main);
}
#Override
protected String doInBackground(String... aurl) {
MDPIActivity.this.runOnUiThread(new Runnable() {
public void run() {
CountryTable country = new CountryTable() ;
country.EnterCountry();
}
});
return null;
}
}
With this, I would like to set the content View and then in background, that the method onBackground works, but I have still to wait for the content view until the onBackground method is not finished.
Thank you.
i don't see any reason for putting the setContentView() in the onPreExecute method, it should be in the onCreate method to avoid any kind of NullPointerException when you will try to find your views, and for your AsyncTask , you should just use the onPostExecute() which is executed after the method doInBackground()
Please try this one, think its work.`class checkCountryAsync extends AsyncTask {
#Override
protected void onPreExecute() {
super.onPreExecute();
setContentView(R.layout.main);
}
#Override
protected String doInBackground(String... aurl) {
CountryTable country = new CountryTable() ;
country.EnterCountry();
return null;
}
}
`
You should try publishProgress() and onProgressUpdate() methods.
I have a function that dynamically creates all my user interface.
What can I do to show a dialog progress while my function is executing, and then dismiss the dialog when my function has finished the user interface?
This is an example of my code:
Sorry, I'm new to android, it is hard for me to understand some code... I will write my code here...
I have this function:
public void principal() {
//CODE TO CREATE ALL THE USER INTERFACE DYNAMICALLY
}
and I have the asyncTask like this:
public class EjecutarTarea extends AsyncTask<Void, Void, Void>
{
protected void onPreExecute() {
dialog = new ProgressDialog(StadioNenaActivity.this);
dialog.setMessage("Cargando..");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
protected Void doInBackground(Void... unused) {
Principal();
return null;
}
#Override
protected void onProgressUpdate(Void... unused) {
}
#Override
protected void onPostExecute(Void unused) {
dialog.dismiss();
}
}
When I execute the asynctask in the onCreate, it crashes:
new EjecutarTarea().execute();
Use an AsyncTask. It gives a fantastic and easy way to load stuff in the background and them paste views in the main thread.
Here is an example of my AsyncTask:
private class LoadingTask extends AsyncTask<Void, Integer, Void> {
private ProgressBar mProg;
private TextView mLoadingText;
#Override protected void onPreExecute() {
mProg = (ProgressBar)findViewById(R.id.launcherbar_loadprogress);
mProg.setTouchDelegate(null);
mProg.setClickable(false);
mProg.setLongClickable(false);
mProg.setOnTouchListener(null);
mProg.setMax(100);
mLoadingText = (TextView) findViewById(R.id.launcheractivity_loadingwhat);
}
#Override protected Void doInBackground(Void... voids) {
try { Thread.sleep(1000); } catch (InterruptedException e) { }
setProgressAndSleep(R.string.loading_log, 29, 250);
LOG.setContext(LauncherActivity.this);
LOG.setDebug(true);
setProgressAndSleep(R.string.loading_database, 43, 250);
AppionDatabase.setContext(LauncherActivity.this);
setProgressAndSleep(R.string.loading_sensors, 57, 250);
Sensor.init(LauncherActivity.this);
setProgressAndSleep(R.string.loading_jobs, 71, 250);
Job.init(LauncherActivity.this);
setProgressAndSleep(R.string.loading_workbenches, 86, 250);
WorkbenchState.init(LauncherActivity.this);
setProgressAndSleep(R.string.loading_application_state, 100, 250);
ApplicationState.setContext(LauncherActivity.this);
startService(new Intent(LauncherActivity.this, BluetoothConnectionService.class));
return null;
}
#Override public void onProgressUpdate(Integer... prog) {
mLoadingText.setText(prog[0]);
mProg.setProgress(prog[1]);
}
#Override public void onPostExecute(Void voids) {
startActivity(new Intent(LauncherActivity.this, HomescreenActivity.class));
}
private void setProgressAndSleep(int text, int progress, int duration) {
try {
publishProgress(new Integer[] {text, progress});
Thread.sleep(duration);
} catch (InterruptedException e) {
LOG.e(TAG, "Failed to sleep thread while loading Application Contexts!", e);
}
}
}
Edit NOTE I recommend not keeping the setProgressAndSleep(int, int int) method. I only use it cause it loads too fast and I really wanted the loading bar. :-P
All changes in Android UI will makes in UI Thread. To run your function in UI thread you need to use mathos runOnUIThread() from activity http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
Hope it help you!
Your best shot is, probably, to use ViewSwitcher to have temporary view with progress bar while you construct other view. Do operations that take time in doInBackground() of AsyncTask but actual operations on UI such as flipping the view must be done in postExecute() or via runOnUIThread(). Progress updates may be done in onProgressUpdate()