1. 程式人生 > >Android學習五 網路程式設計與handler訊息機制

Android學習五 網路程式設計與handler訊息機制

      Android中許多應用需要從網路上獲取內容,而如何從網路上獲取內容,這就需要用到網路程式設計的知識。下面是Android中關於網路程式設計的一些知識。

一、使用httpURLConnection物件訪問網路

    使用UrlConnection請求一個url地址獲取內容的一般步驟如下:

//1.建立一個Url物件
       URL url = new URL(url_str);

//2.獲取一個UrlConnection物件
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
//3.為UrlConnection物件設定一些請求的引數,請求方式,連線的超時時間
        connection.setRequestMethod("GET");//設定請求方式
        connection.setConnectTimeout(1000*10);//設定超時時間

//4.在獲取url請求的資料前需要判斷響應碼,200 :成功,206:訪問部分資料成功   300:跳轉或重定向  400:錯誤 500:伺服器異常
        int code = connection.getResponseCode();

//5.獲取有效資料,並將獲取的流資料解析成String
         InputStream inputStream = connection.getInputStream();
         String result = StreamUtils.streamToString(inputStream);

注意訪問網路需要設定android.permission.INTERNET  這個許可權。

       如果直接在主執行緒中做網路請求的話,可能會ANR:application not response 應用無響應的錯誤,這是因為Android中的耗時操作(請求網路,大檔案的拷貝,資料庫的操作等)需要在子執行緒中去做,但是在子執行緒中不能夠更新控制元件(如Toast的展示及其他介面的修改操作)。這是可能就會產生問題,當即需要請求網路有需要更新UI時該怎麼辦呢?

這是後就需要handler了。

二、handler的使用

     handler可以在子執行緒和主執行緒之間傳遞訊息,當子執行緒中需要更新UI時,只需要把要更新的內容用handler傳遞到主執行緒中,在主執行緒中更新即可。下面來看一下handler的用法。

        1.主執行緒中建立一個Handler
        private Handler handler = new Handler(){
                public void handleMessage(android.os.Message msg) {
                };
        };
        2.重寫handler的handlermessage方法
        3.子執行緒中建立一個Message物件,將獲取的資料繫結給msg
                Message msg = new Message();
                //另一種方式:Message msg = Messge.obtain;
                msg.obj = result;
        4.主執行緒中的handler物件在子執行緒中將message傳送給主執行緒
                handler.sendMessage(msg);
        5.主執行緒中handlermessage方法接受子執行緒發來的資料,就可以做更新UI的操作。

下面來看一段示例程式碼:

 private EditText et_url;
    private TextView tv_source;
    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        //一、獲取控制元件
        et_url = (EditText) findViewById(R.id.et_url);
        Button bt_looksource = (Button) findViewById(R.id.bt_looksource);
        tv_source = (TextView) findViewById(R.id.tv_source);
        //二、繫結點選事件
        bt_looksource.setOnClickListener(this);
        System.out.println("oncreate方法執行緒:"+Thread.currentThread().getName());
    }

    //使用handler在子執行緒和主執行緒之間傳遞訊息的步驟
    //a.在主執行緒中建立一個handler物件
    private Handler handler = new Handler(){
        //b重寫handler物件中的handlerMessage方法,用來接收子執行緒中發來的訊息
        @Override
        public void handleMessage(Message msg) {
            //e.接收子執行緒發來的訊息,處理訊息
            String result = (String)msg.obj;
            System.out.println("獲取到資訊");
            //五、更新UI
            tv_source.setText(result);
        }
    };

    @Override
    public void onClick(View view) {
        //ctrl+alt+t快速新增try catch塊
        try {
            //三、獲取輸入的url地址
            final String url_str = et_url.getText().toString().trim();
            if(TextUtils.isEmpty(url_str)){
                //???
                Toast.makeText(mContext,"url不能為空",Toast.LENGTH_SHORT).show();
                return ;
            }

            System.out.println("onclick方法執行緒:"+Thread.currentThread().getName());

            //四、建立一個子執行緒做網路請求
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("oclick方法runnable執行緒:"+Thread.currentThread().getName());
                        //使用UrlConnection請求一個url地址獲取內容
                        //1.根據url地址建立一個URL物件
                        URL url = new URL(url_str);
                        //2.獲取一個URLConnection物件
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.setRequestMethod("GET");
                        connection.setConnectTimeout(1000*10);
                        System.out.println("第一次請求的請求碼"+connection.getResponseCode());
                        //3.獲取頭部資訊,獲取到重定向後的地址(為了解決返回碼為302的問題)
                        String location = connection.getHeaderField("Location");
                        System.out.println("location "+location+"");
                        //4.為URLConnection設定請求引數(請求方式,連線的超時時間等)
                        url  = new URL(location);
                        connection = (HttpURLConnection) url.openConnection();
                        connection.setRequestMethod("GET");
                        connection.setConnectTimeout(1000*10);
                        //4.判斷響應碼
                        int code = connection.getResponseCode();
                        System.out.println(code);
                        if(code == 200){
                            //5.獲取有效資料,並將資料解析為字串
                            InputStream inputStream = connection.getInputStream();
                            String result = StreamUtils.streamToString(inputStream);
                            //c.子執行緒中建立一個Message物件,用於將子執行緒中的數傳遞給主執行緒
                            Message message = new Message();
                            message.obj = result;
                            //d.使用handler將資料從子執行緒傳遞到主執行緒
                            handler.sendMessage(message);
                        }else{
                            System.out.println("請求url失敗");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
public class StreamUtils {
    public static String streamToString(InputStream in){
        String result = "";
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length = 0;
            while((length = in.read(buffer)) != -1){
                out.write(buffer,0,length);
                out.flush();
            }
            result = out.toString();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;


    }
}
在子執行緒中更新UI的其他集中方法:

        1.使用activity的runOnUiThread方法更新ui,無論當前執行緒是否是主執行緒,都將在主執行緒執行。注意runOnUiThread不能在靜態類中使用
                runOnUiThread(new Runnable() {              
                    @Override
                    public void run() {
                        tv_simple.setText("我被更新了");
                    }
                });
        2.使用handler直接post到主執行緒,handler需要在主執行緒建立
                    //延遲多少毫米執行runnable。
                    mHandler.postDelayed(new Runnable() {      
                    @Override
                    public void run() {
                        tv_simple.setText("我被更新了");
                    }
                }, 1000*5);

還有需要注意的是不能在子執行緒中更新UI並不是絕對的。以下集中情形可以在子執行緒中更新UI:SurfaceView :多媒體視訊播放 ,可以在子執行緒中更新UI; Progress(進度)相關的控制元件:也是可以在子執行緒中更新Ui;審計機制:activity完全顯示的時候審計機制才會去檢測子執行緒有沒有更新Ui。

三、get和post請求

     在請求網路時需要設定請求方式,常用的請求方式有兩種post和get。get的請求內容是跟在URL地址後面(不安全且大小有限制但是簡單),post的請求內容是放在請求體當中(大小無限制,安全,但是繁瑣)。使用post請求相比get請求還需要設定一下內容:

請求頭的設定(不是必需的)
            openConnection.setRequestProperty("Content-Length", body.length()+"");
            openConnection.setRequestProperty("Cache-Control", "max-age=0");
            openConnection.setRequestProperty("Origin", "http://192.168.13.83:8080");
請求內容的設定(必需)
             //設定UrlConnection可以寫請求的內容
            openConnection.setDoOutput(true);
            //獲取一個outputstream,並將內容寫入該流
            openConnection.getOutputStream().write(body.getBytes());

使用post請求方式時還要注意編碼要一致,否則可能產生亂碼。可以使用URLEncode對資料進行編碼。

四、用httpClient做網路請求

       直接上程式碼,get方式:

try{
				String path = "http://192.168.13.83:8080/itheima74/servlet/LoginServlet?username="+URLEncoder.encode(username,"utf-8")+"&pwd="+URLEncoder.encode(password,"utf-8");
				//1.建立一個httpClient物件
				HttpClient httpclient = new DefaultHttpClient();
				
				//2.設定請求的方式
				HttpGet httpget = new HttpGet(path);
				//3.執行一個http請求
				HttpResponse response = httpclient.execute(httpget);
				//4.獲取請求的狀態碼,
				StatusLine statusLine = response.getStatusLine();
				int code = statusLine.getStatusCode();
				
				//5.判斷狀態碼後獲取內容
				if(code == 200){
					HttpEntity entity = response.getEntity();//獲取實體內容,中封裝的有http請求返回的流資訊
					InputStream inputStream = entity.getContent();
					//將流資訊轉換成字串
					String result = StreamUtils.streamToString(inputStream);
					
					Message msg = Message.obtain();
					msg.what = 1;
					msg.obj = result;
					handler.sendMessage(msg);
				}
				
				}catch (Exception e) {
					e.printStackTrace();
				}
post方式:
String path = "http://192.168.13.83:8080/itheima74/servlet/LoginServlet";
	
			AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
			RequestParams params = new RequestParams();
			params.put("username", username);
			params.put("pwd", password);
			
			//url:   parmas:請求時攜帶的引數資訊   responseHandler:是一個匿名內部類接受成功過失敗
			asyncHttpClient.post(path, params, new AsyncHttpResponseHandler() {
				
				@Override
				public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
					//statusCode:狀態碼    headers:頭資訊  responseBody:返回的內容,返回的實體
					
					//判斷狀態碼
					if(statusCode == 200){
						//獲取結果
						try {
							String result = new String(responseBody,"utf-8");
							Toast.makeText(context, result, 0).show();
						} catch (UnsupportedEncodingException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
				}
				
				@Override
				public void onFailure(int statusCode, Header[] headers,
						byte[] responseBody, Throwable error) {
					
				}
			});


相關推薦

Android學習 網路程式設計handler訊息機制

      Android中許多應用需要從網路上獲取內容,而如何從網路上獲取內容,這就需要用到網路程式設計的知識。下面是Android中關於網路程式設計的一些知識。 一、使用httpURLConnection物件訪問網路     使用UrlConnection請求一個url

Android 多執行緒程式設計Handler訊息傳遞機制—重新整理UI主介面

一、為什麼使用Handler   當一個Activity執行的時候,會開啟一條主執行緒,主執行緒主要負責處理與UI相關的事件,主執行緒不允許其他子執行緒操控它,更新UI介面。既然不允許我們在子執行緒中操控UI介面,那麼,像我們平時所見的點選獲取驗證碼,不斷更新

Android自助餐】Handler訊息機制完全解析()鳥瞰總結

Android自助餐Handler訊息機制完全解析(五)鳥瞰與總結 Android自助餐Handler訊息機制完全解析五鳥瞰與總結 Message MessageQueue Handler Looper

Android Handler訊息機制學習

1.概述   Handler允許你傳送和處理Message,以及和執行緒相關聯的Runnable物件。每一個Handler例項都與一個執行緒及該執行緒的MessageQueue相關聯。既當你建立一個Handler時,該Handler必須繫結一個執行緒以及該執行緒的訊息佇列,一旦它被建立,它能把message

學習筆記(六) 網路程式設計資料處理

廢話不多說啦,我們直接學習Android中最常使用的網路技術。 在請求網路之前,我們需要在AndroidManifest中宣告訪問網路的許可權: uses-permission android:name="android.permission.INTER

Android學習總結————Java程式設計技巧開發例項(朱福喜)

第一部分   記於2013年7月21 1.安卓開發環境的安裝 (1)設定相關環境變數 a.JAVA_HOME        D:\Java\jdk1.6.0_29 b.PATH          %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;D:\

7.3(java學習筆記)網路程式設計之UDP

一、UDP   UDP的全稱是User Datagram Protocol(使用者資料報協議),是一種無連線的不安全的傳輸協議,   傳輸資料時傳送方和接收方無需建立連線,所以是不安全的。   傳送時不建立連線直接傳送,傳送後不關注接受方能否接到。UDP只負責發出去,後續的事情與之無關。  

java學習day20--網路程式設計

一.網路模型與協議: OSI 七層模式 : 應用層,表示層,會話層,傳輸層,網路層,鏈路層,物理層 五層模型: 應用層, 傳輸層,網路層,鏈路層,物理層 四層模型 : 應用層, 傳輸層,網路層,鏈路層 應用層:http(超文字傳輸協議) ftp(檔案傳輸協議) stmp (郵件傳送協議) pop

Linux學習網路程式設計(epoll的用法)

言之者無罪,聞之者足以戒。 - “詩序” epoll相關的函式包含在標頭檔案<sys/epoll.h> epoll是Linux核心為處理大批量控制代碼而作了改進的poll,是Linux下多路複用IO介面select/poll的增強版本,它能顯著減少程式在大量併發連線中只有少量活躍

Linux學習網路程式設計(select)

言之者無罪,聞之者足以戒。 - “詩序” 1、阻塞式I/O 下面看一下實現的邏輯: 2、非阻塞式I/O 下面看一下實現的邏輯: 3、I/O複用(select/epoll) (1)  int  select (int maxfdp, fd_set

Linux學習網路程式設計(多程序併發伺服器)

言之者無罪,聞之者足以戒。 - “詩序” 上面我們所說過的通訊都是一個伺服器一個客戶端之間的通訊,下面我們來交流一下多程序併發伺服器的相關知識 邏輯上就是這個樣子的,就是一個伺服器多個客戶端進行資料的傳輸。 1、傳送資料的函式: ssize_t send(int sockfd,

Linux學習網路程式設計(UDP程式設計

言之者無罪,聞之者足以戒。 - “詩序” 前幾篇文章說的都是TCP通訊的問題,這篇文章說一下UDP通訊的相關內容: 下面來看一下基於UDP的獲取時間的客戶伺服器的程式框圖: (1)、建立一個基於IPv4(AF_INET)的資料報套接字(SOCK_DGRAM) (2)、ssize

Linux學習網路程式設計(TCP程式設計 模型總結)

言之者無罪,聞之者足以戒。 - “詩序” TCP通訊也就是伺服器和客戶端的一種通訊方式,它的整體框架為: 針對TCP通訊所用到的函式,我來做一下說明: (1)插座創造一個套接字 int socket(int domain,int type,int protocol) 標頭檔

Linux學習網路程式設計(TCP相關基礎知識)

言之者無罪,聞之者足以戒。 - “詩序”、 1、網路位元組序: 在TCP的編寫過程中需要從網路位元組序轉換到主機位元組序,當然也需要從主機位元組序轉換到網路位元組序 htons 把 unsigned short型別從主機序轉換到網路序htonl把unsigned long型別從

Linux學習網路程式設計(TCP三次握手四次揮手)

言之者無罪,聞之者足以戒。 - “詩序” 1、三次握手: 看一下三次握手的框圖: (1)、伺服器必須準備好接受外來連線 (2)、客戶端呼叫connect來主動開啟一個連線,此時客戶端TCP將會發送一個SYN分節 (3)、伺服器必須確認客戶的SYN (4)、客戶必須確認伺

Linux學習網路程式設計(TCP程式設計

言之者無罪,聞之者足以戒。 - “詩序” 1,TCP是什麼? TCP傳輸控制協議 向用戶程序提供可靠的全雙工位元組流(位元組流:給每一個位元組編序) 2,UDP是什麼? UDP使用者資料報協議 是一種無連線的協議 3,獲取時間服務的客戶端 (1),建立一個的的I

Android Handler訊息機制原始碼解析

好記性不如爛筆頭,今天來分析一下Handler的原始碼實現 Handler機制是Android系統的基礎,是多執行緒之間切換的基礎。下面我們分析一下Handler的原始碼實現。 Handler訊息機制有4個類合作完成,分別是Handler,MessageQueue,Looper,Message Handl

FC 10.2 多執行緒程式設計Handler訊息非同步處理機制

執行緒的基本用法 在子執行緒中更新UI Handler訊息非同步處理機制 Handler訊息非同步處理個人理解   執行緒用於執行比較耗時的操作。 執行緒的基本用法有三個(常用第三種) 1、新建類繼承Thread,重寫父

es6學習:類繼承

before: function Animal(name){ this.name = name; } Animal.prototype.showName = function(){ console.log(this.name); } var a = new Animal('Tom

深入Java網路程式設計NIO(二)

Java NIO 與 Netty NIO NIO的特性/NIO與IO區別: 1)IO是面向流的,NIO是面向緩衝區的; 2)IO流是阻塞的,NIO流是不阻塞的; 3)NIO有選擇器,而IO沒有。 讀資料和寫資料方式: 從通道進行資料讀取 :建立一個緩衝區,然後請求通道讀取資料。