首页 文章

AsyncTask Android示例

提问于
浏览
601

我正在阅读 AsyncTask ,我尝试了下面的简单程序 . 但它似乎没有用 . 我怎样才能使它工作?

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) {
        }
    }
}

我只是想在后台进程中在5秒后更改标签 .

这是我的 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>

16 回答

  • 684

    背景/理论

    AsyncTask 允许您在后台线程上运行任务,同时将结果发布到UI线程 .

    用户应始终能够与应用程序进行交互,因此避免使用从Web下载内容等任务阻止主(UI)线程非常重要 . 这就是我们使用AsyncTask的原因 . 它通过包装UI线程消息队列和处理程序提供了一个简单的接口,允许您发送和处理来自其他线程的可运行对象和消息 .

    实施

    AsyncTask 是一个通用类 . (它的构造函数需要 parameterized types . )

    它使用这些 three generic types:

    Params - 执行时发送给任务的参数类型 .

    Progress - 后台计算期间发布的进度单元的类型 .

    Result - 后台计算结果的类型 .

    并非所有类型都始终由异步任务使用 . 要将类型标记为未使用,只需使用类型Void:private class MyTask extends AsyncTask <Void,Void,Void>

    您可以在 AsyncTask 中覆盖这三个参数 correspond to three primary functions

    • doInBackground(Params...)

    • onProgressUpdate(Progress...)

    • onPostExecute(Result)

    To execute AsyncTask

    调用 execute() 并将参数发送到后台任务 .

    What Happens

    • 在main / UI线程上,调用 onPreExecute() . (初始化此线程中的某些内容,例如在用户界面上显示进度条 . )

    • 在后台线程上,调用 doInBackground(Params...) . (参数是传递给Execute函数的参数 . )

    • 应该发生长时间运行的任务

    • 必须至少覆盖 doInBackground() 才能使用AsyncTask .

    • 调用 publishProgress(Progress...) 以在后台计算仍在执行时更新用户界面中的进度显示 . (例如,为进度条设置动画或在文本字段中显示日志 . )

    • 这会导致 onProgressUpdate() 被调用 .

    • 在后台线程上,从 doInBackground() 返回结果 . 这会触发下一步 .

    • 在main / UI线程上,使用返回的结果调用 onPostExecute() .

    例子

    再次使用阻止任务的示例是从Web下载内容,

    • Example A downloads an image 并将其显示在ImageView中,

    • Example B downloads some files .

    示例A.

    doInBackground() 方法下载图像并将其存储在BitMap类型的对象中 . onPostExecute() 方法获取位图并将其放在ImageView中 .

    class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
        ImageView bitImage;
    
        public DownloadImageTask(ImageView bitImage) {
            this.bitImage = bitImage;
        }
    
        protected Bitmap doInBackground(String... urls) {
            String urldisplay = urls[0];
            Bitmap mBmp = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                mBmp = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return mBmp;
        }
    
        protected void onPostExecute(Bitmap result) {
            bitImage.setImageBitmap(result);
        }
    }
    

    例B

    private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
         protected Long doInBackground(URL... urls) {
             int count = urls.length;
             long totalSize = 0;
             for (int i = 0; i < count; i++) {
                 totalSize += Downloader.downloadFile(urls[i]);
                 publishProgress((int) ((i / (float) count) * 100));
                 // Escape early if cancel() is called
                 if (isCancelled()) break;
             }
             return totalSize;
         }
    
         protected void onProgressUpdate(Integer... progress) {
             setProgressPercent(progress[0]);
         }
    
         protected void onPostExecute(Long result) {
             showDialog("Downloaded " + result + " bytes");
         }
     }
    

    Example B execution

    new DownloadFilesTask().execute(url1, url2, url3);
    
  • 68
    private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> {
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Showing progress dialog
            progressDialog = new ProgressDialog(this);
            progressDialog.setMessage("Loading...");
            progressDialog.setCancelable(false);
            progressDialog.show();
    
        }
    
        @Override
        protected Void doInBackground(Void... arg0) {
    
            //do code here 
    
            return null;
        }
    
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            // Dismiss the progress dialog
            if (progressDialog.isShowing()) {
                progressDialog.dismiss();
            }
    
        }
    
        @Override
        protected void onCancelled() {
    
            super.onCancelled();
            progressDialog.dismiss();
            Toast toast = Toast.makeText(getActivity(),
                    "Error is occured due to some probelm", Toast.LENGTH_LONG);
            toast.setGravity(Gravity.TOP, 25, 400);
            toast.show();
    
        }
    
    }
    
  • 0

    当您在工作线程中时,您无法直接操作Android上的UI元素 .

    当您使用AsyncTask时,请了解回调方法 .

    例如:

    public class MyAyncTask extends AsyncTask<Void, Void, Void>{
    
        @Override
        protected void onPreExecute() {
            // Here you can show progress bar or something on the similar lines.
            // Since you are in a UI thread here.
            super.onPreExecute();
        }
    
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            // After completing execution of given task, control will return here.
            // Hence if you want to populate UI elements with fetched data, do it here.
        }
    
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
            // You can track you progress update here
        }
    
        @Override
        protected Void doInBackground(Void... params) {
            // Here you are in the worker thread and you are not allowed to access UI thread from here.
            // Here you can perform network operations or any heavy operations you want.
            return null;
        }
    }
    

    仅供参考:要从工作线程访问UI线程,可以在视图上使用runOnUiThread()方法或post方法 .

    例如:

    runOnUiThread(new Runnable() {
        textView.setText("something.");
    });
    
    or
        yourview.post(new Runnable() {
        yourview.setText("something");
    });
    

    这将有助于您更好地了解事情 . 因此,在您的情况下,您需要在onPostExecute()方法中设置textview .

  • 4

    带POST请求的示例异步任务:

    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("key1", "value1"));
    params.add(new BasicNameValuePair("key1", "value2"));
    new WEBSERVICEREQUESTOR(URL, params).execute();
    
    class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String>
    {
        String URL;
        List<NameValuePair> parameters;
    
        private ProgressDialog pDialog;
    
        public WEBSERVICEREQUESTOR(String url, List<NameValuePair> params)
        {
            this.URL = url;
            this.parameters = params;
        }
    
        @Override
        protected void onPreExecute()
        {
            pDialog = new ProgressDialog(LoginActivity.this);
            pDialog.setMessage("Processing Request...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
            super.onPreExecute();
        }
    
        @Override
        protected String doInBackground(String... params)
        {
            try
            {
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpEntity httpEntity = null;
                HttpResponse httpResponse = null;
    
                HttpPost httpPost = new HttpPost(URL);
    
                if (parameters != null)
                {
                    httpPost.setEntity(new UrlEncodedFormEntity(parameters));
                }
                httpResponse = httpClient.execute(httpPost);
    
                httpEntity = httpResponse.getEntity();
                return EntityUtils.toString(httpEntity);
    
            }  catch (Exception e)
            {
    
            }
            return "";
        }
    
        @Override
        protected void onPostExecute(String result)
        {
            pDialog.dismiss();
    
            try
            {
    
            }
            catch (Exception e)
            {
    
            }
            super.onPostExecute(result);
        }
    }
    
  • 1

    我的完整答案是here,但这是一个解释性图片,以补充本页面上的其他答案 . 对我来说,了解所有变量的去向是开始时最令人困惑的部分 .

    enter image description here

  • 10

    执行异步任务时,任务将执行4个步骤:

    • onPreExecute()

    • doInBackground(Params ...)

    • onProgressUpdate(进度......)

    • onPostExecute(结果)

    以下是演示示例

    private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
         protected Long doInBackground(URL... urls) {
             int count = urls.length;
             long totalSize = 0;
             for (int i = 0; i < count; i++) {
                 totalSize += Downloader.downloadFile(urls[i]);
                 publishProgress((int) ((i / (float) count) * 100));
                 // Escape early if cancel() is called
                 if (isCancelled()) break;
             }
             return totalSize;
         }
    
         protected void onProgressUpdate(Integer... progress) {
             setProgressPercent(progress[0]);
         }
    
         protected void onPostExecute(Long result) {
             showDialog("Downloaded " + result + " bytes");
         }
     }
    

    一旦你创建了,任务就会非常简单地执行:

    new DownloadFilesTask().execute(url1, url2, url3);
    

    我希望这能帮到您...

  • 8

    移动这两行:

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

    超出你的AsyncTask的 doInBackground 方法并将它们放在 onPostExecute 方法中 . 你的 AsyncTask 应该是这样的:

    private class LongOperation extends AsyncTask<String, Void, String> {
    
        @Override
        protected String doInBackground(String... params) {
            try {
                Thread.sleep(5000); // no need for a loop
            } catch (InterruptedException e) {
                Log.e("LongOperation", "Interrupted", e);
                return "Interrupted";
            }
            return "Executed";
        }      
    
        @Override
        protected void onPostExecute(String result) {               
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText(result);
        }
    }
    
  • 1

    好的,你试图通过另一个线程访问GUI . 这主要是不好的做法 .

    AsyncTask执行另一个线程中 doInBackground() 内的所有内容,该线程无法访问您的视图所在的GUI .

    preExecute()postExecute() 为您提供在此新线程中发生繁重操作之前和之后的GUI访问权限,您甚至可以将长操作的结果传递给 postExecute() ,然后显示任何处理结果 .

    请参阅稍后更新TextView的这些行:

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

    把它们放在 PostExecute()

    然后,在 doInBackground 完成后,您将看到TextView文本已更新 .

    EDIT: 我注意到你的onClick监听器没有检查是否已经选择了哪个View . 我发现最简单的方法是通过switch语句 . 我在下面编辑了一个完整的课程,提出了所有建议以避免混淆 .

    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) {}
        }
    }
    
  • 50

    我确定它正在执行,但您正在尝试更改UI元素在后台线程中,这是不会做的 .

    按如下方式修改您的调用和AsyncTask:

    Calling Class

    Note: 我个人建议在执行AsyncTask线程的地方使用 onPostExecute() ,而不是在扩展AsyncTask本身的类中 . 我认为它使代码更容易阅读,特别是如果您需要在多个地方处理结果略有不同的AsyncTask .

    new LongThread()
    {
        @Override public void onPostExecute(String result)
        {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText(result);
        }
    }.execute("");
    

    LongThread class (extends AsyncTask):

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

    只是:

    LongOperation MyTask = new LongOperation();
    MyTask.execute();
    
  • 6

    你需要声明按钮onclicklistener,一旦点击它调用AsyncTask类的DownloadJson,过程将如下所示:

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            btn = (Button) findViewById(R.id.button1);
    
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                 new DownloadJson().execute();
                }
            });
    
        }
    

    // DownloadJSON AsyncTask
        private class DownloadJson extends AsyncTask<Void, Void, Void> {
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }
    
            @Override
            protected  Void doInBackground(Void... params) {
                newlist = new ArrayList<HashMap<String, String>>();
                 json = jsonParser.makeHttpRequest(json, "POST");
                try {
                    newarray = new JSONArray(json);
                        for (int i = 0; i < countdisplay; i++) {
                            HashMap<String, String> eachnew = new HashMap<String, String>();
                            newobject = newarray.getJSONObject(i);
                            eachnew.put("id", newobject.getString("ID"));
                            eachnew.put("name", newobject.getString("Name"));
                            newlist.add(eachnew);
                        }
                    }
                } catch (JSONException e) {
                    Log.e("Error", e.getMessage());
                    e.printStackTrace();
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Void args) {
                newlisttemp.addAll(newlist);
                NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this,newlisttemp);
                newpager.setAdapter(newadapterpager);
            }
        }
    
  • 3

    这里的概念和代码

    我创建了一个使用Android的AsyncTask的简单示例 . 它以 onPreExecute(), doInBackground(), publishProgress() 开头,最后是 onProgressUpdate() .

    在这个doInBackground()作为后台线程,而其他工作在UI线程 . 您无法访问doInBackground()中的UI元素 . 序列与我提到的相同 .

    但是,如果您需要从 doInBackground 更新任何小部件,您可以 publishProgressdoInBackground 调用 onProgressUpdate 来更新您的UI小部件 .

    class TestAsync extends AsyncTask<Void, Integer, String>
    {
        String TAG = getClass().getSimpleName();
    
        protected void onPreExecute (){
            super.onPreExecute();
            Log.d(TAG + " PreExceute","On pre Exceute......");
        }
    
        protected String doInBackground(Void...arg0) {
            Log.d(TAG + " DoINBackGround","On doInBackground...");
    
            for(int i=0; i<10; i++){
                Integer in = new Integer(i);
                publishProgress(i);
            }
            return "You are at PostExecute";
        }
    
        protected void onProgressUpdate(Integer...a){
            super.onProgressUpdate(a);
            Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
        }
    
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            Log.d(TAG + " onPostExecute", "" + result);
        }
    }
    

    在您的活动中将其称为:

    new TestAsync().execute();
    

    Developer Reference Here

  • 1

    更改您的代码,如下所示:

    @Override
    protected void onPostExecute(String result) {
    
        runOnUiThread(new Runnable() {
            public void run() {
                TextView txt = (TextView) findViewById(R.id.output);
                txt.setText("Executed");
            }
        });
    }
    
  • 0

    我建议您使用此库进行背景设计,让您的生活更轻松https://github.com/Arasthel/AsyncJobLibrary

    它这么简单..

    AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {
    
        @Override
        public void doOnBackground() {
            startRecording();
        }
    });
    
  • 636

    以异步方式执行操作的最短示例:

    class MyAsyncTask extends android.os.AsyncTask {
        @Override
        protected Object doInBackground(Object[] objects) {
            //do something asynchronously
            return null;
        }
    }
    

    要运行它:

    (new MyAsyncTask()).execute();
    
  • 10

    Sample AsyncTask example with progress

    import android.animation.ObjectAnimator;
    import android.os.AsyncTask;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.animation.AccelerateDecelerateInterpolator;
    import android.view.animation.DecelerateInterpolator;
    import android.view.animation.LinearInterpolator;
    import android.widget.Button;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    public class AsyncTaskActivity extends AppCompatActivity implements View.OnClickListener {
    
        Button btn;
        ProgressBar progressBar;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn = (Button) findViewById(R.id.button1);
            btn.setOnClickListener(this);
            progressBar = (ProgressBar)findViewById(R.id.pbar);
        }
    
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.button1:
                    new LongOperation().execute("");
                    break;
            }
        }
    
        private class LongOperation extends AsyncTask<String, Integer, String> {
    
            @Override
            protected String doInBackground(String... params) {
                Log.d("AsyncTask", "doInBackground");
                for (int i = 0; i < 5; i++) {
                    try {
                        Log.d("AsyncTask", "task "+(i + 1));
                        publishProgress(i + 1);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.interrupted();
                    }
                }
                return "Completed";
            }
    
            @Override
            protected void onPostExecute(String result) {
                Log.d("AsyncTask", "onPostExecute");
                TextView txt = (TextView) findViewById(R.id.output);
                txt.setText(result);
                progressBar.setProgress(0);
            }
    
            @Override
            protected void onPreExecute() {
                Log.d("AsyncTask", "onPreExecute");
                TextView txt = (TextView) findViewById(R.id.output);
                txt.setText("onPreExecute");
                progressBar.setMax(500);
                progressBar.setProgress(0);
            }
    
            @Override
            protected void onProgressUpdate(Integer... values) {
                Log.d("AsyncTask", "onProgressUpdate "+values[0]);
                TextView txt = (TextView) findViewById(R.id.output);
                txt.setText("onProgressUpdate "+values[0]);
    
                ObjectAnimator animation = ObjectAnimator.ofInt(progressBar, "progress", 100 * values[0]);
                animation.setDuration(1000);
                animation.setInterpolator(new LinearInterpolator());
                animation.start();
            }
        }
    }
    

相关问题