Fox Fox - 5 months ago 18
Android Question

AsyncTask Android example

I was reading about

AsyncTask
, and I tried the simple program below. But it does not seem to work. How can I make it work?

package com.test;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity {
Button btn;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener((OnClickListener) this);
}

public void onClick(View view){
new LongOperation().execute("");
}

private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
return null;
}

@Override
protected void onPostExecute(String result) {
}

@Override
protected void onPreExecute() {
}

@Override
protected void onProgressUpdate(Void... values) {
}
}
}


I am just trying to change the label after 5 seconds in the background process.

This is my main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="false"
android:max="10"
android:padding="10dip">
</ProgressBar>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Progress" >
</Button>
<TextView android:id="@+id/output"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Replace"/>
</LinearLayout>

Answer

Ok you are trying to access the GUI via another thread. This, in the main, is not good practice.

The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.

preExecute() and postExecute() offer you access to GUI before and after the heavy lifting occurs in this new thread, you can even pass the result of the long operation to postExecute() to then show any results of processing.

See these lines where you are later updating your TextView:

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

put them in PostExecute()

You will then see your TextView text updated after the doInBackground completes.

EDIT: I noticed that your onClick listener does not check to see which View has been selected. I find the easiest way to do this is via switch statements. I have a complete class edited below with all suggestions to save confusion.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity implements OnClickListener {

    Button btn;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button) findViewById(R.id.button1);
        // because we implement OnClickListener we only have to pass "this"
        // (much easier)
        btn.setOnClickListener(this);
    }

    public void onClick(View view) {
        // detect the view that was "clicked"
        switch (view.getId()) {
        case R.id.button1:
            new LongOperation().execute("");
            break;
        }
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed"); // txt.setText(result);
            // might want to change "executed" for the returned string passed
            // into onPostExecute() but that is upto you
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
}