目錄
- 寫在前面的話
- 一、HTTP協定
- 二、通路網絡
-
- (一)概述
- (二)測試-浏覽網絡圖檔
- 三、開源項目-網絡請求
-
- (一)概述
- (二)測試-AsyncHttpClient+SmartImageView
- 四、補充
寫在前面的話
1、參考自:https://b23.tv/NwYxbp
2、内容如果有不對的,希望可以指出或補充。
3、新知識。
一、HTTP協定
超文本傳輸協定(Hyper Text Transfer Protocol,HTTP):規定了浏覽器和伺服器間互相通信的規則。是一種請求/響應式(用戶端發送請求,服務端産生響應)的協定。整個響應的過程就是HTTP通信過程。
- HTTP請求:當用戶端與伺服器建立連接配接後,向伺服器端發送的請求
- HTTP響應:當伺服器端接收到用戶端的請求後會做出響應,如傳回資料。
二、通路網絡
(一)概述
1、GET和POSTGET請求方式:以實體的方式得到由請求URL所指向的資源資訊,它向伺服器送出的參數跟在(拼接)請求URL後面 [ 浏覽器位址欄中可以看到 ] ,參數和URL間用“?”隔開,每一個參數間用“&”隔開。
使用該方式通路網絡,URL的長度(參數也是)一般需小于1k(1K=1KB=1024Bytes)
。
注意:使用URLEncoder.encode(“值”)對參數進行URL編碼(因為需要傳到浏覽器位址欄中)。
POST請求方式:向伺服器送出請求時需要在請求後附加實體。它向伺服器送出的參數在請求後的實體中(請求體中),
該方式對URL的長度沒有限制
。采用該方式送出資料時,使用者在浏覽器中看不到向伺服器送出的請求參數,
是以POST方式相較GET方式更安全
。
無論時GET還是POST都需要注意編碼方式的一緻(用戶端與服務端)。
2、HttpURLConnection通路網絡使用步驟需要new子線程
。
從安卓6.0開始,Google已經移除了HttpClient庫的支援,
推薦使用HttpURLConnection
。
建立url→建立HttpURLConnection對象→設定請求方式、逾時時間(防止連接配接被阻塞時無響應),擷取伺服器傳回的輸入流→關閉HTTP連接配接
3、Handler消息機制在Android聯網操作中,都是在子線程中
。
是一種異步回調機制,主要負責主線程(主要就是UI界面)與子線程(耗時的操作)進行通信。其主要對象(四個關鍵對象):
- Message:消息。
- Handler:處理者,主要負責Message的發送與處理。
- MessageQueue:消息隊列,主要用來存放Handler發送過來的消息,并按照
的規則執行。先入先出
- Looper:消息循環,不斷地從MessageQueue中抽取Message并交給Handler處理。
大概使用流程:Handler發送Message→存入MessageQueue→通過Looper取出Message→Handler處理Message→在HandlerMessage()中進行處理
(二)測試-浏覽網絡圖檔
功能:檢視網絡上的圖檔(使用HttpURLConnection的GET請求擷取網絡圖檔)。
1 依賴-項目清單檔案

2 布局
2 主要代碼
MainActivity.java
package com.example.testhttp;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private static final int CHANGE_UI = 1;//建立常量
private static final int ERROR = 2;
private HttpURLConnection conn;
private EditText testEd;
private ImageView testImg;
//在主線程建立消息處理器Handler
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == CHANGE_UI){
Bitmap bitmap = (Bitmap) msg.obj;
testImg.setImageBitmap(bitmap);//
}else if(msg.what == ERROR){
Toast.makeText(MainActivity.this,"顯示錯誤",Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//擷取控件
testEd = findViewById(R.id.test_ed);
testImg = findViewById(R.id.test_img);
}
public void test(View view){
//擷取到輸入位址
String path = testEd.getText().toString().trim();
//判斷輸入是否為空
if(TextUtils.isEmpty(path)){
Toast.makeText(this,"不能為空",Toast.LENGTH_SHORT).show();
}else {
//在子線程中請求網絡
new Thread(){ //開啟一個線程
private Bitmap bitmap;
@Override
public void run() {
//連接配接伺服器GET請求擷取到圖檔
try {
URL url = new URL(path);//建立url
//根據url發送HTTP請求
conn = (HttpURLConnection) url.openConnection();
//設定
conn.setRequestMethod("GET");//請求方式
conn.setConnectTimeout(5000);//逾時時間5秒
int code = conn.getResponseCode();//得到服務端傳回的響應碼
//請求網絡成功的傳回碼為200
if(code == 200){
//擷取輸入流,裡面就是想要的資訊
InputStream is = conn.getInputStream();
//is轉換為Bitmap對象
bitmap = BitmapFactory.decodeStream(is);
///将更改主界面的消息發送給主線程
Message msg = new Message();
msg.what = CHANGE_UI;//用于區分不同的消息
msg.obj = bitmap;//攜帶對應的資料
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
Message msg = new Message();
msg.what = ERROR;
handler.sendMessage(msg);
}
///關閉連接配接
conn.disconnect();
}
}.start();
}
}
}
3 效果展示
運作結果如下。
三、開源項目-網絡請求
Day22内容。
(一)概述
1、AsyncHttpClientAsyncHttpClient:Async就是異步的意思。可以處理異步(多條線程中處理任務)HTTP請求,也就是
會自動開啟一個子線程
,并通過匿名内部類處理回調結果。将對應的方法做了封裝。需要導入。
HTTP異步請求都是位于非UI線程中,不會阻塞UI操作,AsyncHttpClient通過線程池處理并發請求,處理檔案上傳、下載下傳,
響應結果自動成JSON格式
。
AsyncHttpClient常用類:
- AsyncHttpClient:異步用戶端請求的類,提供了get、put、post、delete、head等請求方法。
- AsyncHttpResponseHandler:繼承自ResponseHandlerInterface。是通路網絡後回調的接口,接收請求結果,如果通路成功則回調其中的OnSucess方法,否則回調OnFailure方法。
SmartImageView:主要用于加速從網絡上加載圖檔,它繼承自Android自帶的ImageView元件。需要導入也需要布局。
(二)測試-AsyncHttpClient+SmartImageView
功能:解析伺服器上的JSON檔案并将其顯示到ListView控件上。
1、依賴SmartImageView的jar包下載下傳
對應的build.gradle檔案
清單檔案
① 配置伺服器
下載下傳apache-tomcat-8.5.61.zip
② 啟動伺服器
③ 測試
test_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--嵌套部分-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--進度條部分-->
<LinearLayout
android:id="@+id/show_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="visible">
<!--進度條-->
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加載中..."/>
</LinearLayout>
<!--展示部分ListView-->
<ListView
android:id="@+id/show_news"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"/>
</FrameLayout>
</LinearLayout>
test_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp">
<!--加載圖檔部分-->
<com.loopj.android.image.SmartImageView
android:id="@+id/item_img"
android:layout_width="80dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"/>
<!--文本部分-->
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@id/item_img"
android:text="标題"
android:textColor="@color/black"
android:textSize="18sp" />
<TextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/item_title"
android:layout_toRightOf="@id/item_img"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:text="描述"
android:textSize="14sp" />
<TextView
android:id="@+id/item_talk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="10dp"
android:text="評論"
android:textSize="12sp"
android:layout_marginLeft="60dp"
android:layout_gravity="bottom"
android:textColor="#aaaaaa"/>
</RelativeLayout>
4、代碼 NewsInfo.java
package com.example.testhttp;
//JSON資料内容
public class NewsInfo {
//字段名與JSON檔案資料字段一緻
private String icon;//圖檔路徑
private String title;//标題
private String content;//描述的内容
private int type;//類型
private long comment;//評論數
public NewsInfo(String icon, String title, String content, int type, long comment) {
this.icon = icon;
this.title = title;
this.content = content;
this.type = type;
this.comment = comment;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public long getComment() {
return comment;
}
public void setComment(long comment) {
this.comment = comment;
}
}
JsonParse.java
為了友善以後更改,做如下的添加。
Test2.java
package com.example.testhttp;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.image.SmartImageView;
import java.util.List;
import cz.msebera.android.httpclient.Header;
public class Test2 extends AppCompatActivity {
//test_activity
private LinearLayout showLoading;
private ListView showNews;
//test_item
private SmartImageView itemImg;
private TextView itemTitle,itemText,itemTalk;
private List<NewsInfo> newsInfoList;//聲明集合
private NewsInfo newsInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
//擷取到控件
showLoading = findViewById(R.id.show_loading);
showNews = findViewById(R.id.show_news);
//填充資料
fillData();//調用
}
//使用AsyncHttpClient通路網絡
private void fillData() {
//建立AsyncHttpClient對象
AsyncHttpClient client = new AsyncHttpClient();
//預設為GET請求方式
client.get(getString(R.string.server_url), new AsyncHttpResponseHandler() {
@Override
//請求成功
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
//調用JsonParse工具類解析JSON檔案資料
String json = new String(responseBody, "utf-8");//轉換為json資料
newsInfoList = JsonParse.getNewsInfo(json);
if (newsInfoList == null) {
Toast.makeText(Test2.this, "解析失敗", Toast.LENGTH_SHORT).show();
} else {
//更新界面
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
showLoading.setVisibility(View.INVISIBLE);//進度條改成不顯示
showNews.setAdapter(new NewsAdapter());//展示
}
},5000);//5秒後執行
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Toast.makeText(Test2.this, "請求失敗", Toast.LENGTH_SHORT).show();
}
});
}
//ListView擴充卡
private class NewsAdapter extends BaseAdapter {
//條目對象
@Override
public Object getItem(int position) {
return null;
}
//條目id
@Override
public long getItemId(int position) {
return 0;
}
@Override
//listview的條目數
public int getCount() {
return newsInfoList.size();
}
@Override
//擷取到條目資訊view
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(Test2.this, R.layout.test_item, null);
//擷取控件
itemImg = view.findViewById(R.id.item_img);
itemTitle = view.findViewById(R.id.item_title);
itemText = view.findViewById(R.id.item_text);
itemTalk = view.findViewById(R.id.item_talk);
newsInfo = newsInfoList.get(position);//擷取到要顯示的資料
//SmartImageView加載指定路徑的圖檔
//參數1:具體路徑,參數2、3:顯示成功/失敗加載的圖檔
itemImg.setImageUrl(newsInfo.getIcon(), R.mipmap.ic_launcher, R.mipmap.ic_launcher);
//設定标題
itemTitle.setText(newsInfo.getTitle());
//設定描述文字
itemText.setText(newsInfo.getContent());
//設定類型
int type = newsInfo.getType();
switch (type) {
//不同新聞類型設定不同的顔色和不同的内容
//其他的則是預設的文字内容
case 1:
itemTalk.setText("評論數:" + newsInfo.getComment());
break;
case 2:
//紅色的專題文字
itemTalk.setTextColor(Color.RED);
itemTalk.setText("專題新聞");
break;
case 3:
itemTalk.setTextColor(Color.BLUE);
itemTalk.setText("LIVE");
break;
}
return view;//傳回條目資訊
}
}
}
5、效果展示 運作結果如下。
四、補充
1、com.google.gson.stream.MalformedJsonException報錯的解決辦法
我發生的問題是源自JSON資料的問題,格式多了個在“}”前多了個“,”。