android-asynctask asynctask使用 - AsyncTask Android示例




in example (13)

只是:

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

我正在閱讀關於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>

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

@Override
protected void onPostExecute(String result) {

    runOnUiThread(new Runnable() {
        public void run() {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
        }
    });
}

 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();

    }

}

當執行一個異步任務時,任務需要經過4個步驟:

  1. onPreExecute()
  2. doInBackground(參數...)
  3. onProgressUpdate(進展...)
  4. 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);

我希望這能幫到您...


我建議通過使用這個庫進行後台工作來讓你的生活更輕鬆https://github.com/Arasthel/AsyncJobLibrary

它的這個簡單..

AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {

    @Override
    public void doOnBackground() {
        startRecording();
    }
});

理論

AsyncTask允許您在後台線程上運行任務,同時將結果發佈到UI線程。

用戶應該始終能夠與應用程序進行交互,避免阻止主(UI)線程執行諸如從Web下載內容等任務很重要。 這是我們使用AsyncTask

UI線程有一個消息隊列和一個處理程序,它允許您通常從其他線程發送和處理可運行對象和消息。 AsyncTask使用簡單的接口來封裝這種行為。

履行

AsyncTask是一個通用類。 (這意味著它的構造函數需要參數化類型,每個泛型參數都被定義為一個帶有三個點的Java變量參數: ...所以在技術上以數組的形式傳遞)。

AsyncTask使用的三種類型是ParamsProgressResult

  1. Params - 執行時發送給任務的參數類型
  2. 進度 - 發布的類型,用於在後台計算期間更新進度
  3. 結果 - 背景計算結果的類型

這三個參數對應於您可以在AsyncTask重寫的三個主要函數:

  • doInBackground()
  • onProgressUpdate()
  • onPostExecute()

    也:

  • onPreExecute()

執行AsyncTask

調用Execute參數發送到後台任務。

怎麼了

  1. 在主/ UI線程上, onPreExecute 。 (在此線程中初始化某些內容。)
  2. 在後台線程上,使用傳遞給Execute函數的參數調用doInBackground()
    • 必須重寫至少doInBackground()才能使用AsyncTask。
    • 長期運行的任務應該發生在哪裡
    • 使用Progress參數調用publishProgress()以隨著長時間運行任務的進度更新一些UI。 這會導致onProgressUpdate()被調用。
  3. 在後台線程上,結果將從doInBackground()任務返回,這會導致
  4. 在main / UI線程上,使用返回的結果調用onPostExecute()

再次使用攔截任務的示例是從Web下載某個內容,以下示例會下載一個圖像並將其顯示在ImageView中。 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);
    }
}

你需要聲明按鈕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);
        }
    }

帶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);
    }
}

當您在工作線程中時,無法直接操作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。


好的,你試圖通過另一個線程訪問GUI。 這主要是不好的做法。

AsyncTask執行另一個線程內的doInBackground()所有內容,該線程無法訪問視圖所在的GUI。

preExecute()postExecute()在這個新線程發生繁重事件之前和之後為您提供對GUI的訪問,甚至可以將長操作的結果傳遞給postExecute()以顯示任何處理結果。

看到以後更新TextView的位置:

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

把它們放在PostExecute()

doInBackground完成後,您將看到更新的TextView文本。

編輯:我注意到你的onClick監聽器不檢查,看看哪個視圖已被選中。 我發現最簡單的方法是通過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) {}
    }
}

移動這兩行:

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

我確定它正在正確執行,但是你正試圖在後台線程中更改UI元素,而這是不行的。

如下修改你的通話和AsyncTask:

調用類

注意:我個人建議在任何執行AsyncTask線程的地方使用onPostExecute()而不要在擴展AsyncTask本身的類中使用onPostExecute() 。 我認為它使代碼更易於閱讀,特別是如果您需要在多個地方處理結果稍有不同的AsyncTask。

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

LongThread類(擴展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";
}      

儘管接受的答案是正確的,但是使用名為Icepick的庫在Android上保存活動狀態的方法更快更容易。Icepick是一個註釋處理器,負責處理為您保存和恢復狀態時使用的所有樣板代碼。

用Icepick做這樣的事情:

class MainActivity extends Activity {
  @State String username; // These will be automatically saved and restored
  @State String password;
  @State int age;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Icepick.restoreInstanceState(this, savedInstanceState);
  }

  @Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Icepick.saveInstanceState(this, outState);
  }
}

這樣做是一樣的:

class MainActivity extends Activity {
  String username;
  String password;
  int age;

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putString("MyString", username);
    savedInstanceState.putString("MyPassword", password);
    savedInstanceState.putInt("MyAge", age); 
    /* remember you would need to actually initialize these variables before putting it in the
    Bundle */
  }

  @Override
  public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    username = savedInstanceState.getString("MyString");
    password = savedInstanceState.getString("MyPassword");
    age = savedInstanceState.getInt("MyAge");
  }
}

Icepick將使用任何保存其狀態的對象Bundle







android android-asynctask