安卓基礎_9

1登錄案例

[1]使用httpurlconnection實現get請求

1.
2.
3. //[1]獲取用戶名和密碼
4. final String name = et_name.getText().toString().trim();
5. final String pwd = et_pwd.getText().toString().trim();
6. //[2]判斷用戶名密碼是否爲空
7. if (TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)) {
8. Toast.makeText(getApplicationContext(), “用戶名密碼不能爲空”, Toast.LENGTH_LONG).show();
9. }else {
10. //[3]把用戶名和密碼提交到服務器 get形式提交數據就是以組拼url地址的形式提交
11. //http://localhost:8080/login/LoginServlet?username=abc&password=123
12.
13. //創建一個子線程
14. new Thread() {
15. public void run() {
16. try {
17. String path = “http://192.168.81.95:8080/login/LoginServlet?username=“+name+”&password=”+pwd+”“;
18. //[1.2]創建URL 對象指定我們要訪問的 網址(路徑)
19. URL url = new URL(path);
20. //[1.3]拿到httpurlconnection對象 用於發送或者接收數據
21. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
22. //[1.4]設置發送get請求
23. conn.setRequestMethod(“GET”);//get要求大寫 默認就是get請求
24. //[1.5]設置請求超時時間
25. conn.setConnectTimeout(5000);
26. //[1.6]獲取服務器返回的狀態碼
27. int code = conn.getResponseCode();
28. //[1.7]如果code == 200 說明請求成功
29. if (code == 200) {
30. //[1.8]獲取服務器返回的數據
31. InputStream in = conn.getInputStream(); //流裏面的數據是
32.
33. //[1.9]把in轉換成String
34. String content = StreamTools.readInputSream(in);
35.
36. //[2.0]顯示一個土司給用戶友好提示
37. showToast(content);
38.
39. }
40.
41. } catch (Exception e) {
42. e.printStackTrace();
43.
44. }
45.
46.
47. }
48. }.start();
49.
50.
51.
52.
53. }
54.
55.
56.
57.

[2]使用httpurlconnection類實現post請求

總結和post區別

1)請求路徑不同

2)自己要組拼請求體的內容

3)設置post請求  conn.setRequestMethod("POST");

4)數據是以流的形式寫給服務器

1.
2.
3.
4. //[1]獲取用戶名和密碼
5. final String name = et_name.getText().toString().trim();
6. final String pwd = et_pwd.getText().toString().trim();
7. //[2]判斷用戶名密碼是否爲空
8. if (TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)) {
9. Toast.makeText(getApplicationContext(), “用戶名密碼不能爲空”, Toast.LENGTH_LONG).show();
10. }else {
11. //[3]把用戶名和密碼提交到服務器 get形式提交數據就是以組拼url地址的形式提交
12. //http://localhost:8080/login/LoginServlet?username=abc&password=123
13.
14. //創建一個子線程
15. new Thread() {
16. public void run() {
17. try {
18. //★★★★區別一 訪問的路徑不同 http://192.168.81.95:8080/login/LoginServlet
19. String path = “http://192.168.81.95:8080/login/LoginServlet“;
20.
21. //★★★★區別一 post請求是以請求體的形式提交
22. String data = “username=”+name+”&password=”+pwd+”“;
23.
24. //[1.2]創建URL 對象指定我們要訪問的 網址(路徑)
25. URL url = new URL(path);
26. //[1.3]拿到httpurlconnection對象 用於發送或者接收數據
27. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
28. //[1.4]設置發送get請求 //★★★★區別三 設置post請求
29. conn.setRequestMethod(“POST”);//get要求大寫 默認就是get請求
30. //[1.5]設置請求超時時間
31. conn.setConnectTimeout(5000);
32.
33. //[1.5.1]//★★★★區別四 官方提示要進行post請求 要多設置個參數
34. conn.setDoOutput(true); //設置一個標記 允許conn像服務器輸出數據 數據是以流的形式寫給服務器
35. conn.getOutputStream().write(data.getBytes());
36.
37. //[1.6]獲取服務器返回的狀態碼
38. int code = conn.getResponseCode();
39. //[1.7]如果code == 200 說明請求成功
40. if (code == 200) {
41. //[1.8]獲取服務器返回的數據
42. InputStream in = conn.getInputStream(); //流裏面的數據是
43.
44. //[1.9]把in轉換成String
45. String content = StreamTools.readInputSream(in);
46.
47. //[2.0]顯示一個土司給用戶友好提示
48. showToast(content);
49.
50. }
51.
52. } catch (Exception e) {
53. e.printStackTrace();
54.
55. }
56.
57.
58. }
59. }.start();
60.
61.
62.
63.
64. }
65.
66.
67.
68.
69.

2.httpclient方式提交數據

[1]這個類其實就是一個開源項目 是谷歌工程師把它加到了Android開發環境中 所以不需要在導入jar包

[2]這個類是一個接口 不能new對象要找實現子類

[3]谷歌工程師命名技巧 : base… default….simple….

[4]對http協議封裝 可以執行http的請求

使用httpclient方式實現get請求 代碼如下

1.// [4]創建httpclient實例 由於這個類是一個接口所以我們 實現類
2. DefaultHttpClient client = new DefaultHttpClient();
3. // [4.1]創建httpGet實現類
4. HttpGet get = new HttpGet(path);
5. // [4.2]拿着client對象執行一個get請求
6. HttpResponse response = client.execute(get);
7. // [4.3]獲取服務器返回的狀態碼
8. int code = response.getStatusLine().getStatusCode();
9. if (code == 200) {
10. // [4.4]獲取服務器返回的數據
11. InputStream in = response.getEntity().getContent();
12. // [4.5]把in轉換成String
13. String content = StreamTools.readInputSream(in);
14. // [4.6]展示土司
15. showToast(content);
16.
17. }

使用httpclient實現post請求

1.
2. try {
3. // ★★★★區別一 訪問的路徑不同
4. // http://192.168.81.95:8080/login/LoginServlet
5. String path = “http://192.168.81.95:8080/login/LoginServlet“;
6. // [4]創建httpclient實例 由於這個類是一個接口所以我們 實現類
7. DefaultHttpClient client = new DefaultHttpClient();
8. // [4.1]創建httpPost實現類
9. HttpPost post = new HttpPost(path);
10.
11. //[4.2]
12. //準備parameters 他是list
13. List parameters = new ArrayList();
14. //[4.3]封裝name的數據 第一個參數:要和你Servlet request獲取數據參數的key一樣 第二個參數
15. BasicNameValuePair nameValuePair = new BasicNameValuePair(“username”, name);
16. BasicNameValuePair pwdValuePair = new BasicNameValuePair(“password”, pwd);
17. //[4.4]把nameValuePair 和 pwdValuePair加入daolist集合
18. parameters.add(nameValuePair);
19. parameters.add(pwdValuePair);
20. //[4.5]準備UrlEncodedFormEntity
21. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters);
22. //[4.6]封裝請求的數據 編程思想:參數需要什麼就準備什麼
23. post.setEntity(entity);
24.
25. // [4.2]拿着client對象執行一個post請求
26. HttpResponse response = client.execute(post);
27. // [4.3]獲取服務器返回的狀態碼
28. int code = response.getStatusLine().getStatusCode();
29. if (code == 200) {
30. // [4.4]獲取服務器返回的數據
31. InputStream in = response.getEntity().getContent();
32. // [4.5]把in轉換成String
33. String content = StreamTools.readInputSream(in);
34. // [4.6]展示土司
35. showToast(content);
36.
37. }
38.
39.
40.
41. } catch (Exception e) {
42. e.printStackTrace();
43.
44. }
45.
46.

3 asyncHttpclient實現數據的提交

使用開源項目 思路 new 對象 調用方法

使用get方式提交數據

1.
2.
3. //[1]獲取用戶名和密碼
4. final String name = et_name.getText().toString().trim();
5. final String pwd = et_pwd.getText().toString().trim();
6. //[2]創建asynchttpclient對象
7. AsyncHttpClient client = new AsyncHttpClient();
8. String path = “http://192.168.81.95:8080/login/LoginServlet?username=
9. + name + “&password=” + pwd + “”;
10. //[3]執行get請求 url就是你要請求的地址
11. client.get(path, new AsyncHttpResponseHandler() {
12. //請求成功
13. @Override
14. public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
15. Toast.makeText(getApplicationContext(), new String(responseBody), Toast.LENGTH_LONG).show();
16.
17. }
18. //請求失敗
19. @Override
20. public void onFailure(int statusCode, Header[] headers,
21. byte[] responseBody, Throwable error) {
22.
23. }
24. });
25.
26.
27.

使用post實現數據提交代碼如下

1.
2.
3. // [1]獲取用戶名和密碼
4. final String name = et_name.getText().toString().trim();
5. final String pwd = et_pwd.getText().toString().trim();
6. //[2]創建asynchttpclient對象
7. AsyncHttpClient client = new AsyncHttpClient();
8. String path = “http://192.168.81.95:8080/login/LoginServlet“;
9. RequestParams params = new RequestParams();
10. params.put(“username”, name);
11. params.put(“password”, pwd);
12.
13. //[3]執行post請求
14. client.post(path, params, new AsyncHttpResponseHandler() {
15.
16. @Override
17. public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
18. Toast.makeText(getApplicationContext(), new String(responseBody), Toast.LENGTH_LONG).show();
19. }
20.
21. @Override
22. public void onFailure(int statusCode, Header[] headers,
23. byte[] responseBody, Throwable error) {
24.
25. }
26. });
27.
28.

4 多線程下載

[1]服務器上有一個文件 把文件下載到客戶端

[2]爲什麼開多個線程 因爲可以提高下載速度

[3]不是開的線程越多下載越快 10000 3 手機迅雷 手雷 建議開3-5個

[4]還受真實服務器帶寬的影響

[5]開多個線程可以提供下載速度 就是cpu搶佔了更多的資源

5 如何實現多線程下載

注意的問題最後拿.exe 安裝文件做測試

元數據 : 數據的數據 我買了一個小汽車

計算每個線程下載的開始位置和結束位置

實現的步驟

[1]獲取文件大小

1.
2. //一 獲取feiq的文件大小
3. try {
4. //[1.2]創建URL 對象指定我們要訪問的 網址(路徑)
5. URL url = new URL(path);
6. //[1.3]拿到httpurlconnection對象 用於發送或者接收數據
7. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
8. //[1.4]設置發送get請求
9. conn.setRequestMethod(“GET”);//get要求大寫 默認就是get請求
10. //[1.5]設置請求超時時間
11. conn.setConnectTimeout(5000);
12. //[1.6]獲取服務器返回的狀態碼
13. int code = conn.getResponseCode();
14. //[1.7]如果code == 200 說明請求成功
15. if (code == 200) {
16. //[1.8]獲取文件的大小
17. int length = conn.getContentLength();
}

[2]在客戶端創建一個大小和服務器一模一樣的文件

1.RandomAccessFile raf = new RandomAccessFile(“temp.exe”, “rw”);
2.raf.setLength(length);

[3]假設開三個線程 算出每個線程下載大小

int blockSize = length / threadCount;

[4]算出每個線程下載的開始位置和結束位置

1.for (int i = 0; i < threadCount; i++) {
2. int startIndex = i*blockSize; //每個線程下載的開始位置
3. int endIndex = (i+1)*blockSize-1; //每個線程下載的結束位置
4. //判斷是否是最後一個線程
5. if (i == threadCount-1) {
6. endIndex = length-1;
7. }
8.
9. }

[5]在for循環裏面開啓多個線程去服務器下載數據 把數據寫到temp.exe文件裏

1.
2. //定義線程 去服務器下載數據
3. private static class DownLoadThread extends Thread{
4. private int startIndex;
5. private int endIndex;
6. private int threadId; //代表線程的id
7. public DownLoadThread(int startIndex,int endIndex,int threadId){
8. this.startIndex = startIndex;
9. this.endIndex = endIndex;
10. this.threadId = threadId;
11.
12. }
13.
14. @Override
15. public void run() {
16.
17. try {
18. //[1.2]創建URL 對象指定我們要訪問的 網址(路徑)
19. URL url = new URL(path);
20. //[1.3]拿到httpurlconnection對象 用於發送或者接收數據
21. HttpURLConnection conn = (HttpURLConnection) url
22. .openConnection();
23. //[1.4]設置發送get請求
24. conn.setRequestMethod(“GET”);//get要求大寫 默認就是get請求
25. //[1.5]設置請求超時時間
26. conn.setConnectTimeout(5000);
27.
28. //[1.5.1]設置一個range頭 告訴服務器每個線程下載的開始位置和結束位置
29. conn.setRequestProperty(“Range”, “bytes=”+startIndex+”-“+endIndex);
30.
31. //[1.6]獲取服務器返回的狀態碼
32. int code = conn.getResponseCode();
33. //[1.7]如果code == 200 說明請求成功 206代表請求部分資源成功
34. if (code == 206) {
35. //[1.8]獲取服務器返回的數據 數據是流的形式返回
36. InputStream in = conn.getInputStream();
37.
38. //[1.9]把數據寫到temp.exe裏面
39. RandomAccessFile raf = new RandomAccessFile(“temp.exe”, “rw”);
40. raf.seek(startIndex);//每個線程從開始位置寫
41.
42. int len = 0;
43. byte[] buffer = new byte[1024];
44. while((len = in.read(buffer))!=-1){
45. raf.write(buffer, 0, len);
46. }
47. raf.close();//關閉流
48. in.close();
49.
50. System.out.println(“線程id:”+threadId+”下載完了”);
51.
52. }
53.
54. } catch (Exception e) {
55. e.printStackTrace();
56.
57. }
58.
59. }
60. }
61.

[6]實現斷點續傳的邏輯

原理:就是把當前線程下載的位置給記錄起來 下次在下載的時候 如果中斷過 就繼續上次斷的位置繼續下

    1. total+=len; //代表當前線程下載的大小
  1. int currentThreadPosition = startIndex + total; //當前線程下載的位置 把這個位置存到一個普通的文本文件中

    1. //把當前線程下載的位置存到txt中
  2. RandomAccessFile raff = new RandomAccessFile(getFileName(path)+threadId+”.txt”, “rwd”); //rwd 這個模式直接把數據同步到底層設備
  3. raff.write(String.valueOf(currentThreadPosition).getBytes());
  4. raff.close();

    把當前線程下載的位置記錄下來後 如果中斷過 ,然後把上次下載的位置讀取出來 繼續上次的位置 繼續下

1.if (file.exists()&&file.length()>0) {
2. //說明中斷過 就把上次下載的位置讀出來
3. FileInputStream fis = new FileInputStream(file);
4. BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
5. String lastDownLoadPosition = bufr.readLine(); //就是上次下載 的位置
6. //改變當前線程下載的開始位置
7. startIndex = Integer.parseInt(lastDownLoadPosition);
8. bufr.close();
9.
10. System.out.println(“線程id:”+threadId+”真實下載的位置:”+startIndex+”—-“+endIndex);
11. }
12.

6 Android下實現多線程下載

與進度相關的控件都可以在子線程直接更新ui. progressBar progressDialog

軟件存在的問題: 好的軟件不是開發出來的 是不斷調試出來 安智市場 類似 360手機助手 豌豆莢 91

4000多行.

[1]反饋 什麼軟件 我都沒有sd卡 文件下載到哪裏了

[2]下載的軟件 也不判斷一下是否是wifi狀態 下載了幾個文件之後 手機流量的沒有了

[3]三星的手機上能夠正常運行 小米手機

[4]下載的文件 也不判斷一下下載的文件是否攜帶病毒

[5]………

7 使用開源項目實現多線程下載

[1]導包

[2]實現代碼如下

1.
2. //獲取下載文件的路徑
3. String path = et_path.getText().toString().trim();
4. //[1]創建HttpUtils 對象的實例
5. HttpUtils http = new HttpUtils();
6. //[2]調用下載的方法 target把下載文件的數據存儲到什麼位置上 autoResume 是否支持斷點續傳
7. http.download(path, “/mnt/sdcard/test.exe”, true, new RequestCallBack() {
8.
9. //下載成功後調用
10. @Override
11. public void onSuccess(ResponseInfo responseInfo) {
12. Toast.makeText(getApplicationContext(),”下載成功”,1).show();
13. }
14.
15. //更新進度條的進度
16. @Override
17. public void onLoading(long total, long current, boolean isUploading) {
18.
19. pb.setMax((int) total);//設置進度條的最進度
20. pb.setProgress((int) current); //設置進度條的當前進度
21.
22. }
23.
24.
25. //下載失敗
26. @Override
27. public void onFailure(HttpException error, String msg) {
28.
29. }
30. });
31.
32.
33.

[3]在實際開發中 什麼情況用開源項目 QQ影音  公司新聞客戶端   什麼情況自己寫.

2天網絡編程總結

網頁源碼查看器: httpurlconnection 用於發送和接收數據

消息機制 handler

圖片查看器 要把流轉換成bitmap 通過位圖工廠類

新聞客戶端 綜合案例 listview 數據適配器 聯網獲取數據 在子線程更新ui xml解析

smartImageView

自定義了一個開源項目

登錄案例 使用httpurlconnection的方式實現數據提交 掌握

httpclient 這個類實現數據的提交 瞭解

asynchttpclient 開源項目實現數據的提交 掌握

多線程下載的邏輯

斷點續傳

移植Android項目

使用開源項目xutils實現多線程下載

發佈了57 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章