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沒有。 讀資料和寫資料方式: 從通道進行資料讀取 :建立一個緩衝區,然後請求通道讀取資料。