Android利用非同步任務AsyncTask發送post請求擷取json資料

來源:互聯網
上載者:User

標籤:

AsyncTask,是android提供的輕量級的非同步類,可以直接繼承AsyncTask,在類中實現非同步作業,提供介面反饋當前非同步執行的程度(可以通過介面實現UI進度更新),最後反饋執行的結果給UI主線程.

使用的優點:

l  簡單,快捷

l  過程可控

使用的缺點:

l  在使用多個非同步作業和並需要進行Ui變更時,就變得複雜起來.

2 )Handler非同步實現的原理和適用的優缺點


AsyncTask介紹Android的AsyncTask比Handler更輕量級一些,適用於簡單的非同步處理。首先明確Android之所以有Handler和AsyncTask,都是為了不阻塞主線程(UI線程),且UI的更新只能在主線程中完成,因此非同步處理是不可避免的。

Android為了降低這個開發難度,提供了AsyncTask。AsyncTask就是一個封裝過的背景工作類,顧名思義就是非同步任務。

AsyncTask直接繼承於Object類,位置為android.os.AsyncTask。要使用AsyncTask工作我們要提供三個泛型參數,並重載幾個方法(至少重載一個)。

AsyncTask定義了三種泛型型別 Params,Progress和Result。

  • Params 啟動任務執行的輸入參數,比如HTTP請求的URL。
  • Progress 背景工作執行的百分比。
  • Result 後台執行任務最終返回的結果,比如String。

使用過AsyncTask 的同學都知道一個非同步載入資料最少要重寫以下這兩個方法:

  • doInBackground(Params…) 後台執行,比較耗時的操作都可以放在這裡。注意這裡不能直接操作UI。此方法在後台線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。
  • onPostExecute(Result)  相當於Handler 處理UI的方式,在這裡面可以使用在doInBackground 得到的結果處理操作UI。 此方法在主線程執行,任務執行的結果作為此方法的參數返回

有必要的話你還得重寫以下這三個方法,但不是必須的:

  • onProgressUpdate(Progress…)   可以使用進度條增加使用者體驗度。 此方法在主線程執行,用於顯示任務執行的進度。
  • onPreExecute()        這裡是終端使用者調用Excute時的介面,當任務執行之前開始調用此方法,可以在這裡顯示進度對話方塊。
  • onCancelled()             使用者調用取消時,要做的操作

使用AsyncTask類,以下是幾條必須遵守的準則:

  • Task的執行個體必須在UI thread中建立;
  • execute方法必須在UI thread中調用;
  • 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法;
  • 該task只能被執行一次,否則多次調用時將會出現異常;

下面給出一個我寫的小demo,僅供大家參考,運行結果



首先是AysncTask類:

package ly.asynctasktest;import android.content.Context;import android.os.AsyncTask;import android.widget.TextView;import android.widget.Toast;/** * Created by kfbmac3 on 16/7/8. */    /*      AsyncTask是個抽象類別,使用時需要繼承這個類,然後調用execute()方法。注意繼承時需要設定三個泛型Params,      Progress和Result的類型,如AsyncTask<Void,Inetger,Void>:     Params是指調用execute()方法時傳入的參數類型和doInBackgound()的參數類型     Progress是指更新進度時傳遞的參數類型,即publishProgress()和onProgressUpdate()的參數類型     Result是指doInBackground()的傳回值類型        doInBackgound() 這個方法是繼承AsyncTask必須要實現的,運行於後台,耗時的操作可以在這裡做        publishProgress() 更新進度,給onProgressUpdate()傳遞進度參數        onProgressUpdate() 在publishProgress()調用完被調用,更新進度     */public class UpdateTextTask extends AsyncTask<Void,Integer,String> {    private Context context;    private String url;    private String postValue;    private TextView text;    UpdateTextTask(Context context , String string , String postValue , TextView text) {        this.context = context;        this.url = string;        this.postValue = postValue;        this.text = text;    }    /**     * 運行在UI線程中,在調用doInBackground()之前執行     * 該方法運行在UI線程當中,並且運行在UI線程當中 可以對UI空間進行設定     */    @Override    protected void onPreExecute() {        Toast.makeText(context,"開始執行",Toast.LENGTH_SHORT).show();    }    /**     * 後台啟動並執行方法,可以運行非UI線程,可以執行耗時的方法     * 這裡的Void參數對應AsyncTask中的第一個參數     * 這裡的String傳回值對應AsyncTask的第三個參數     * 該方法並不運行在UI線程當中,主要用於非同步作業,所有在該方法中不能對UI當中的空間進行設定和修改     * 但是可以調用publishProgress方法觸發onProgressUpdate對UI進行操作     */    @Override    protected String doInBackground(Void... params) {        int i=0;        while(i<10){            i++;            //publishProgress 更新進度,給onProgressUpdate()傳遞進度參數            publishProgress(i);            try {                Thread.sleep(1000);            } catch (InterruptedException e) {            }        }        String result = Common.postGetJson(url,postValue);        //第三個參數為String 所以此處return一個String類型的資料        return result;    }    /**     * 這裡的String參數對應AsyncTask中的第三個參數(也就是接收doInBackground的傳回值)     * 運行在ui線程中,在doInBackground()執行完畢後執行,傳入的參數為doInBackground()返回的結果     */    @Override    protected void onPostExecute(String i) {        Toast.makeText(context,i,Toast.LENGTH_SHORT).show();        text.setText(i);    }    /**     * 在publishProgress()被調用以後執行,publishProgress()用於更新進度     * 這裡的Intege參數對應AsyncTask中的第二個參數     * 在doInBackground方法當中,,每次調用publishProgress方法都會觸發onProgressUpdate執行     * onProgressUpdate是在UI線程中執行,所有可以對UI空間進行操作     */    @Override    protected void onProgressUpdate(Integer... values)    {        //第二個參數為Int        text.setText(""+values[0]);    }}

接下來是發送http請求的方法:

package ly.asynctasktest;import android.util.Log;import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.List;import java.util.Map;/** * Created by kfbmac3 on 16/5/20. */public class Common {    public static String postGetJson(String url, String content) {        try {            URL mUrl = new URL(url);            HttpURLConnection mHttpURLConnection = (HttpURLConnection) mUrl.openConnection();            //設定連結逾時時間            mHttpURLConnection.setConnectTimeout(15000);            //設定讀取逾時時間            mHttpURLConnection.setReadTimeout(15000);            //佈建要求參數            mHttpURLConnection.setRequestMethod("POST");            //添加Header            mHttpURLConnection.setRequestProperty("Connection", "Keep-Alive");            //接收輸入資料流            mHttpURLConnection.setDoInput(true);            //傳遞參數時需要開啟            mHttpURLConnection.setDoOutput(true);            //Post方式不能緩衝,需手動設定為false            mHttpURLConnection.setUseCaches(false);            mHttpURLConnection.connect();            DataOutputStream dos = new DataOutputStream(mHttpURLConnection.getOutputStream());            String postContent = content;            dos.write(postContent.getBytes());            dos.flush();            // 執行完dos.close()後,POST請求結束            dos.close();            // 擷取代碼傳回值            int respondCode = mHttpURLConnection.getResponseCode();            Log.d("respondCode","respondCode="+respondCode );            // 擷取返回內容類型            String type = mHttpURLConnection.getContentType();            Log.d("type", "type="+type);            // 擷取返回內容的字元編碼            String encoding = mHttpURLConnection.getContentEncoding();            Log.d("encoding", "encoding="+encoding);            // 擷取返回內容長度,單位位元組            int length = mHttpURLConnection.getContentLength();            Log.d("length", "length=" + length);//            // 擷取頭資訊的Key//            String key = mHttpURLConnection.getHeaderField(idx);//            Log.d("key", "key="+key);            // 擷取完整的頭資訊Map            Map<String, List<String>> map = mHttpURLConnection.getHeaderFields();            if (respondCode == 200) {                // 擷取響應的輸入資料流對象                InputStream is = mHttpURLConnection.getInputStream();                // 建立位元組輸出資料流對象                ByteArrayOutputStream message = new ByteArrayOutputStream();                // 定義讀取的長度                int len = 0;                // 定義緩衝區                byte buffer[] = new byte[1024];                // 按照緩衝區的大小,迴圈讀取                while ((len = is.read(buffer)) != -1) {                    // 根據讀取的長度寫入到os對象中                    message.write(buffer, 0, len);                }                // 釋放資源                is.close();                message.close();                // 返回字串                String msg = new String(message.toByteArray());                Log.d("Common", msg);                return msg;            }            return "fail";        }catch(Exception e){            return "error";        }    }}

MainActivity:

package ly.asynctasktest;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import java.net.URLEncoder;public class MainActivity extends AppCompatActivity {    private Button btn;    private TextView text;    private String url = "http://192.168.24.104:3000/users";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btn = (Button) findViewById(R.id.btn);        text = (TextView) findViewById(R.id.text);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Update();            }        });    }    private void Update(){        try{            String value = URLEncoder.encode("username", "UTF-8") + "=" +                    URLEncoder.encode("anwei", "UTF-8") + "&" +                    URLEncoder.encode("userfullname", "UTF-8") + "=" +                    URLEncoder.encode("安威", "UTF-8");            UpdateTextTask updatetext = new UpdateTextTask(this, url, value , text);            updatetext.execute();        }catch(Exception e){            text.setText("error");        }    }}

需要注意的問題依然是要在AndroidManifest.xml檔案中添加網路許可權:

    <uses-permission android:name="android.permission.INTERNET"/>

文中的url是我用node.js寫的一個簡單後台,接收到post資訊後在MongoDB中尋找資料並返回,後台接收到的資料


想試試的朋友可以自己搭建一個簡單的後台,這裡奉上我的AndroidStudio項目(不包含node.js後台)點擊開啟連結

如果有不足之處,歡迎大家指出!!!朋友們如果有高見,也歡迎您不吝指導!!!

Android利用非同步任務AsyncTask發送post請求擷取json資料

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.